aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/lib/security
diff options
context:
space:
mode:
authorGravatar Craig Tiller <ctiller@google.com>2017-08-29 14:16:14 -0700
committerGravatar Craig Tiller <ctiller@google.com>2017-08-29 14:16:14 -0700
commite944c5d4907732b2bc0a9c6e355ff1e6a65b37e2 (patch)
tree7be516e29013f54061921af50862ad736b8fb020 /src/core/lib/security
parent33aeabad66e8083d47f47ddc4bafa4483f1585f8 (diff)
parent33b51aaa755b2e5f10aade60b67f216bff86cb36 (diff)
Merge branch 'stats' into stats_histo
Diffstat (limited to 'src/core/lib/security')
-rw-r--r--src/core/lib/security/credentials/composite/composite_credentials.c122
-rw-r--r--src/core/lib/security/credentials/credentials.c26
-rw-r--r--src/core/lib/security/credentials/credentials.h74
-rw-r--r--src/core/lib/security/credentials/credentials_metadata.c77
-rw-r--r--src/core/lib/security/credentials/fake/fake_credentials.c47
-rw-r--r--src/core/lib/security/credentials/fake/fake_credentials.h4
-rw-r--r--src/core/lib/security/credentials/iam/iam_credentials.c45
-rw-r--r--src/core/lib/security/credentials/iam/iam_credentials.h2
-rw-r--r--src/core/lib/security/credentials/jwt/jwt_credentials.c51
-rw-r--r--src/core/lib/security/credentials/jwt/jwt_credentials.h2
-rw-r--r--src/core/lib/security/credentials/jwt/jwt_verifier.c17
-rw-r--r--src/core/lib/security/credentials/oauth2/oauth2_credentials.c201
-rw-r--r--src/core/lib/security/credentials/oauth2/oauth2_credentials.h17
-rw-r--r--src/core/lib/security/credentials/plugin/plugin_credentials.c165
-rw-r--r--src/core/lib/security/credentials/plugin/plugin_credentials.h16
-rw-r--r--src/core/lib/security/transport/client_auth_filter.c159
-rw-r--r--src/core/lib/security/transport/security_connector.c57
-rw-r--r--src/core/lib/security/transport/security_connector.h29
-rw-r--r--src/core/lib/security/transport/security_handshaker.c4
-rw-r--r--src/core/lib/security/transport/server_auth_filter.c89
20 files changed, 743 insertions, 461 deletions
diff --git a/src/core/lib/security/credentials/composite/composite_credentials.c b/src/core/lib/security/credentials/composite/composite_credentials.c
index 77d7b04627..09fd60a12c 100644
--- a/src/core/lib/security/credentials/composite/composite_credentials.c
+++ b/src/core/lib/security/credentials/composite/composite_credentials.c
@@ -32,88 +32,98 @@
typedef struct {
grpc_composite_call_credentials *composite_creds;
size_t creds_index;
- grpc_credentials_md_store *md_elems;
- grpc_auth_metadata_context auth_md_context;
- void *user_data;
grpc_polling_entity *pollent;
- grpc_credentials_metadata_cb cb;
+ grpc_auth_metadata_context auth_md_context;
+ grpc_credentials_mdelem_array *md_array;
+ grpc_closure *on_request_metadata;
+ grpc_closure internal_on_request_metadata;
} grpc_composite_call_credentials_metadata_context;
static void composite_call_destruct(grpc_exec_ctx *exec_ctx,
grpc_call_credentials *creds) {
grpc_composite_call_credentials *c = (grpc_composite_call_credentials *)creds;
- size_t i;
- for (i = 0; i < c->inner.num_creds; i++) {
+ for (size_t i = 0; i < c->inner.num_creds; i++) {
grpc_call_credentials_unref(exec_ctx, c->inner.creds_array[i]);
}
gpr_free(c->inner.creds_array);
}
-static void composite_call_md_context_destroy(
- grpc_exec_ctx *exec_ctx,
- grpc_composite_call_credentials_metadata_context *ctx) {
- grpc_credentials_md_store_unref(exec_ctx, ctx->md_elems);
- gpr_free(ctx);
-}
-
-static void composite_call_metadata_cb(grpc_exec_ctx *exec_ctx, void *user_data,
- grpc_credentials_md *md_elems,
- size_t num_md,
- grpc_credentials_status status,
- const char *error_details) {
+static void composite_call_metadata_cb(grpc_exec_ctx *exec_ctx, void *arg,
+ grpc_error *error) {
grpc_composite_call_credentials_metadata_context *ctx =
- (grpc_composite_call_credentials_metadata_context *)user_data;
- if (status != GRPC_CREDENTIALS_OK) {
- ctx->cb(exec_ctx, ctx->user_data, NULL, 0, status, error_details);
- return;
- }
-
- /* Copy the metadata in the context. */
- if (num_md > 0) {
- size_t i;
- for (i = 0; i < num_md; i++) {
- grpc_credentials_md_store_add(ctx->md_elems, md_elems[i].key,
- md_elems[i].value);
+ (grpc_composite_call_credentials_metadata_context *)arg;
+ if (error == GRPC_ERROR_NONE) {
+ /* See if we need to get some more metadata. */
+ if (ctx->creds_index < ctx->composite_creds->inner.num_creds) {
+ grpc_call_credentials *inner_creds =
+ ctx->composite_creds->inner.creds_array[ctx->creds_index++];
+ if (grpc_call_credentials_get_request_metadata(
+ exec_ctx, inner_creds, ctx->pollent, ctx->auth_md_context,
+ ctx->md_array, &ctx->internal_on_request_metadata, &error)) {
+ // Synchronous response, so call ourselves recursively.
+ composite_call_metadata_cb(exec_ctx, arg, error);
+ GRPC_ERROR_UNREF(error);
+ }
+ return;
}
+ // We're done!
}
-
- /* See if we need to get some more metadata. */
- if (ctx->creds_index < ctx->composite_creds->inner.num_creds) {
- grpc_call_credentials *inner_creds =
- ctx->composite_creds->inner.creds_array[ctx->creds_index++];
- grpc_call_credentials_get_request_metadata(
- exec_ctx, inner_creds, ctx->pollent, ctx->auth_md_context,
- composite_call_metadata_cb, ctx);
- return;
- }
-
- /* We're done!. */
- ctx->cb(exec_ctx, ctx->user_data, ctx->md_elems->entries,
- ctx->md_elems->num_entries, GRPC_CREDENTIALS_OK, NULL);
- composite_call_md_context_destroy(exec_ctx, ctx);
+ GRPC_CLOSURE_SCHED(exec_ctx, ctx->on_request_metadata, GRPC_ERROR_REF(error));
+ gpr_free(ctx);
}
-static void composite_call_get_request_metadata(
+static bool composite_call_get_request_metadata(
grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
grpc_polling_entity *pollent, grpc_auth_metadata_context auth_md_context,
- grpc_credentials_metadata_cb cb, void *user_data) {
+ grpc_credentials_mdelem_array *md_array, grpc_closure *on_request_metadata,
+ grpc_error **error) {
grpc_composite_call_credentials *c = (grpc_composite_call_credentials *)creds;
grpc_composite_call_credentials_metadata_context *ctx;
-
ctx = gpr_zalloc(sizeof(grpc_composite_call_credentials_metadata_context));
- ctx->auth_md_context = auth_md_context;
- ctx->user_data = user_data;
- ctx->cb = cb;
ctx->composite_creds = c;
ctx->pollent = pollent;
- ctx->md_elems = grpc_credentials_md_store_create(c->inner.num_creds);
- grpc_call_credentials_get_request_metadata(
- exec_ctx, c->inner.creds_array[ctx->creds_index++], ctx->pollent,
- auth_md_context, composite_call_metadata_cb, ctx);
+ ctx->auth_md_context = auth_md_context;
+ ctx->md_array = md_array;
+ ctx->on_request_metadata = on_request_metadata;
+ GRPC_CLOSURE_INIT(&ctx->internal_on_request_metadata,
+ composite_call_metadata_cb, ctx, grpc_schedule_on_exec_ctx);
+ while (ctx->creds_index < ctx->composite_creds->inner.num_creds) {
+ grpc_call_credentials *inner_creds =
+ ctx->composite_creds->inner.creds_array[ctx->creds_index++];
+ if (grpc_call_credentials_get_request_metadata(
+ exec_ctx, inner_creds, ctx->pollent, ctx->auth_md_context,
+ ctx->md_array, &ctx->internal_on_request_metadata, error)) {
+ if (*error != GRPC_ERROR_NONE) break;
+ } else {
+ break;
+ }
+ }
+ // If we got through all creds synchronously or we got a synchronous
+ // error on one of them, return synchronously.
+ if (ctx->creds_index == ctx->composite_creds->inner.num_creds ||
+ *error != GRPC_ERROR_NONE) {
+ gpr_free(ctx);
+ return true;
+ }
+ // At least one inner cred is returning asynchronously, so we'll
+ // return asynchronously as well.
+ return false;
+}
+
+static void composite_call_cancel_get_request_metadata(
+ grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
+ grpc_credentials_mdelem_array *md_array, grpc_error *error) {
+ grpc_composite_call_credentials *c = (grpc_composite_call_credentials *)creds;
+ for (size_t i = 0; i < c->inner.num_creds; ++i) {
+ grpc_call_credentials_cancel_get_request_metadata(
+ exec_ctx, c->inner.creds_array[i], md_array, GRPC_ERROR_REF(error));
+ }
+ GRPC_ERROR_UNREF(error);
}
static grpc_call_credentials_vtable composite_call_credentials_vtable = {
- composite_call_destruct, composite_call_get_request_metadata};
+ composite_call_destruct, composite_call_get_request_metadata,
+ composite_call_cancel_get_request_metadata};
static grpc_call_credentials_array get_creds_array(
grpc_call_credentials **creds_addr) {
diff --git a/src/core/lib/security/credentials/credentials.c b/src/core/lib/security/credentials/credentials.c
index b1f1e82076..8a67c9865b 100644
--- a/src/core/lib/security/credentials/credentials.c
+++ b/src/core/lib/security/credentials/credentials.c
@@ -38,13 +38,10 @@
/* -- Common. -- */
grpc_credentials_metadata_request *grpc_credentials_metadata_request_create(
- grpc_call_credentials *creds, grpc_credentials_metadata_cb cb,
- void *user_data) {
+ grpc_call_credentials *creds) {
grpc_credentials_metadata_request *r =
gpr_zalloc(sizeof(grpc_credentials_metadata_request));
r->creds = grpc_call_credentials_ref(creds);
- r->cb = cb;
- r->user_data = user_data;
return r;
}
@@ -104,18 +101,25 @@ void grpc_call_credentials_release(grpc_call_credentials *creds) {
grpc_exec_ctx_finish(&exec_ctx);
}
-void grpc_call_credentials_get_request_metadata(
+bool grpc_call_credentials_get_request_metadata(
grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
grpc_polling_entity *pollent, grpc_auth_metadata_context context,
- grpc_credentials_metadata_cb cb, void *user_data) {
+ grpc_credentials_mdelem_array *md_array, grpc_closure *on_request_metadata,
+ grpc_error **error) {
if (creds == NULL || creds->vtable->get_request_metadata == NULL) {
- if (cb != NULL) {
- cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_OK, NULL);
- }
+ return true;
+ }
+ return creds->vtable->get_request_metadata(
+ exec_ctx, creds, pollent, context, md_array, on_request_metadata, error);
+}
+
+void grpc_call_credentials_cancel_get_request_metadata(
+ grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
+ grpc_credentials_mdelem_array *md_array, grpc_error *error) {
+ if (creds == NULL || creds->vtable->cancel_get_request_metadata == NULL) {
return;
}
- creds->vtable->get_request_metadata(exec_ctx, creds, pollent, context, cb,
- user_data);
+ creds->vtable->cancel_get_request_metadata(exec_ctx, creds, md_array, error);
}
grpc_security_status grpc_channel_credentials_create_security_connector(
diff --git a/src/core/lib/security/credentials/credentials.h b/src/core/lib/security/credentials/credentials.h
index c45c2e957c..04a54b0ca8 100644
--- a/src/core/lib/security/credentials/credentials.h
+++ b/src/core/lib/security/credentials/credentials.h
@@ -138,48 +138,39 @@ grpc_channel_credentials *grpc_channel_credentials_from_arg(
grpc_channel_credentials *grpc_channel_credentials_find_in_args(
const grpc_channel_args *args);
-/* --- grpc_credentials_md. --- */
+/* --- grpc_credentials_mdelem_array. --- */
typedef struct {
- grpc_slice key;
- grpc_slice value;
-} grpc_credentials_md;
+ grpc_mdelem *md;
+ size_t size;
+} grpc_credentials_mdelem_array;
-typedef struct {
- grpc_credentials_md *entries;
- size_t num_entries;
- size_t allocated;
- gpr_refcount refcount;
-} grpc_credentials_md_store;
+/// Takes a new ref to \a md.
+void grpc_credentials_mdelem_array_add(grpc_credentials_mdelem_array *list,
+ grpc_mdelem md);
-grpc_credentials_md_store *grpc_credentials_md_store_create(
- size_t initial_capacity);
+/// Appends all elements from \a src to \a dst, taking a new ref to each one.
+void grpc_credentials_mdelem_array_append(grpc_credentials_mdelem_array *dst,
+ grpc_credentials_mdelem_array *src);
-/* Will ref key and value. */
-void grpc_credentials_md_store_add(grpc_credentials_md_store *store,
- grpc_slice key, grpc_slice value);
-void grpc_credentials_md_store_add_cstrings(grpc_credentials_md_store *store,
- const char *key, const char *value);
-grpc_credentials_md_store *grpc_credentials_md_store_ref(
- grpc_credentials_md_store *store);
-void grpc_credentials_md_store_unref(grpc_exec_ctx *exec_ctx,
- grpc_credentials_md_store *store);
+void grpc_credentials_mdelem_array_destroy(grpc_exec_ctx *exec_ctx,
+ grpc_credentials_mdelem_array *list);
/* --- grpc_call_credentials. --- */
-/* error_details must be NULL if status is GRPC_CREDENTIALS_OK. */
-typedef void (*grpc_credentials_metadata_cb)(
- grpc_exec_ctx *exec_ctx, void *user_data, grpc_credentials_md *md_elems,
- size_t num_md, grpc_credentials_status status, const char *error_details);
-
typedef struct {
void (*destruct)(grpc_exec_ctx *exec_ctx, grpc_call_credentials *c);
- void (*get_request_metadata)(grpc_exec_ctx *exec_ctx,
+ bool (*get_request_metadata)(grpc_exec_ctx *exec_ctx,
grpc_call_credentials *c,
grpc_polling_entity *pollent,
grpc_auth_metadata_context context,
- grpc_credentials_metadata_cb cb,
- void *user_data);
+ grpc_credentials_mdelem_array *md_array,
+ grpc_closure *on_request_metadata,
+ grpc_error **error);
+ void (*cancel_get_request_metadata)(grpc_exec_ctx *exec_ctx,
+ grpc_call_credentials *c,
+ grpc_credentials_mdelem_array *md_array,
+ grpc_error *error);
} grpc_call_credentials_vtable;
struct grpc_call_credentials {
@@ -191,15 +182,29 @@ struct grpc_call_credentials {
grpc_call_credentials *grpc_call_credentials_ref(grpc_call_credentials *creds);
void grpc_call_credentials_unref(grpc_exec_ctx *exec_ctx,
grpc_call_credentials *creds);
-void grpc_call_credentials_get_request_metadata(
+
+/// Returns true if completed synchronously, in which case \a error will
+/// be set to indicate the result. Otherwise, \a on_request_metadata will
+/// be invoked asynchronously when complete. \a md_array will be populated
+/// with the resulting metadata once complete.
+bool grpc_call_credentials_get_request_metadata(
grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
grpc_polling_entity *pollent, grpc_auth_metadata_context context,
- grpc_credentials_metadata_cb cb, void *user_data);
+ grpc_credentials_mdelem_array *md_array, grpc_closure *on_request_metadata,
+ grpc_error **error);
+
+/// Cancels a pending asynchronous operation started by
+/// grpc_call_credentials_get_request_metadata() with the corresponding
+/// value of \a md_array.
+void grpc_call_credentials_cancel_get_request_metadata(
+ grpc_exec_ctx *exec_ctx, grpc_call_credentials *c,
+ grpc_credentials_mdelem_array *md_array, grpc_error *error);
/* Metadata-only credentials with the specified key and value where
asynchronicity can be simulated for testing. */
grpc_call_credentials *grpc_md_only_test_credentials_create(
- const char *md_key, const char *md_value, int is_async);
+ grpc_exec_ctx *exec_ctx, const char *md_key, const char *md_value,
+ bool is_async);
/* --- grpc_server_credentials. --- */
@@ -238,14 +243,11 @@ grpc_server_credentials *grpc_find_server_credentials_in_args(
typedef struct {
grpc_call_credentials *creds;
- grpc_credentials_metadata_cb cb;
grpc_http_response response;
- void *user_data;
} grpc_credentials_metadata_request;
grpc_credentials_metadata_request *grpc_credentials_metadata_request_create(
- grpc_call_credentials *creds, grpc_credentials_metadata_cb cb,
- void *user_data);
+ grpc_call_credentials *creds);
void grpc_credentials_metadata_request_destroy(
grpc_exec_ctx *exec_ctx, grpc_credentials_metadata_request *r);
diff --git a/src/core/lib/security/credentials/credentials_metadata.c b/src/core/lib/security/credentials/credentials_metadata.c
index fcfdd52d20..ccd39e610f 100644
--- a/src/core/lib/security/credentials/credentials_metadata.c
+++ b/src/core/lib/security/credentials/credentials_metadata.c
@@ -24,65 +24,36 @@
#include "src/core/lib/slice/slice_internal.h"
-static void store_ensure_capacity(grpc_credentials_md_store *store) {
- if (store->num_entries == store->allocated) {
- store->allocated = (store->allocated == 0) ? 1 : store->allocated * 2;
- store->entries = gpr_realloc(
- store->entries, store->allocated * sizeof(grpc_credentials_md));
+static void mdelem_list_ensure_capacity(grpc_credentials_mdelem_array *list,
+ size_t additional_space_needed) {
+ size_t target_size = list->size + additional_space_needed;
+ // Find the next power of two greater than the target size (i.e.,
+ // whenever we add more space, we double what we already have).
+ size_t new_size = 2;
+ while (new_size < target_size) {
+ new_size *= 2;
}
+ list->md = gpr_realloc(list->md, sizeof(grpc_mdelem) * new_size);
}
-grpc_credentials_md_store *grpc_credentials_md_store_create(
- size_t initial_capacity) {
- grpc_credentials_md_store *store =
- gpr_zalloc(sizeof(grpc_credentials_md_store));
- if (initial_capacity > 0) {
- store->entries = gpr_malloc(initial_capacity * sizeof(grpc_credentials_md));
- store->allocated = initial_capacity;
- }
- gpr_ref_init(&store->refcount, 1);
- return store;
-}
-
-void grpc_credentials_md_store_add(grpc_credentials_md_store *store,
- grpc_slice key, grpc_slice value) {
- if (store == NULL) return;
- store_ensure_capacity(store);
- store->entries[store->num_entries].key = grpc_slice_ref_internal(key);
- store->entries[store->num_entries].value = grpc_slice_ref_internal(value);
- store->num_entries++;
+void grpc_credentials_mdelem_array_add(grpc_credentials_mdelem_array *list,
+ grpc_mdelem md) {
+ mdelem_list_ensure_capacity(list, 1);
+ list->md[list->size++] = GRPC_MDELEM_REF(md);
}
-void grpc_credentials_md_store_add_cstrings(grpc_credentials_md_store *store,
- const char *key,
- const char *value) {
- if (store == NULL) return;
- store_ensure_capacity(store);
- store->entries[store->num_entries].key = grpc_slice_from_copied_string(key);
- store->entries[store->num_entries].value =
- grpc_slice_from_copied_string(value);
- store->num_entries++;
-}
-
-grpc_credentials_md_store *grpc_credentials_md_store_ref(
- grpc_credentials_md_store *store) {
- if (store == NULL) return NULL;
- gpr_ref(&store->refcount);
- return store;
+void grpc_credentials_mdelem_array_append(grpc_credentials_mdelem_array *dst,
+ grpc_credentials_mdelem_array *src) {
+ mdelem_list_ensure_capacity(dst, src->size);
+ for (size_t i = 0; i < src->size; ++i) {
+ dst->md[dst->size++] = GRPC_MDELEM_REF(src->md[i]);
+ }
}
-void grpc_credentials_md_store_unref(grpc_exec_ctx *exec_ctx,
- grpc_credentials_md_store *store) {
- if (store == NULL) return;
- if (gpr_unref(&store->refcount)) {
- if (store->entries != NULL) {
- size_t i;
- for (i = 0; i < store->num_entries; i++) {
- grpc_slice_unref_internal(exec_ctx, store->entries[i].key);
- grpc_slice_unref_internal(exec_ctx, store->entries[i].value);
- }
- gpr_free(store->entries);
- }
- gpr_free(store);
+void grpc_credentials_mdelem_array_destroy(
+ grpc_exec_ctx *exec_ctx, grpc_credentials_mdelem_array *list) {
+ for (size_t i = 0; i < list->size; ++i) {
+ GRPC_MDELEM_UNREF(exec_ctx, list->md[i]);
}
+ gpr_free(list->md);
}
diff --git a/src/core/lib/security/credentials/fake/fake_credentials.c b/src/core/lib/security/credentials/fake/fake_credentials.c
index 67e74f7b92..ac9017850f 100644
--- a/src/core/lib/security/credentials/fake/fake_credentials.c
+++ b/src/core/lib/security/credentials/fake/fake_credentials.c
@@ -98,49 +98,44 @@ const char *grpc_fake_transport_get_expected_targets(
static void md_only_test_destruct(grpc_exec_ctx *exec_ctx,
grpc_call_credentials *creds) {
grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)creds;
- grpc_credentials_md_store_unref(exec_ctx, c->md_store);
+ GRPC_MDELEM_UNREF(exec_ctx, c->md);
}
-static void on_simulated_token_fetch_done(grpc_exec_ctx *exec_ctx,
- void *user_data, grpc_error *error) {
- grpc_credentials_metadata_request *r =
- (grpc_credentials_metadata_request *)user_data;
- grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)r->creds;
- r->cb(exec_ctx, r->user_data, c->md_store->entries, c->md_store->num_entries,
- GRPC_CREDENTIALS_OK, NULL);
- grpc_credentials_metadata_request_destroy(exec_ctx, r);
-}
-
-static void md_only_test_get_request_metadata(
+static bool md_only_test_get_request_metadata(
grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
grpc_polling_entity *pollent, grpc_auth_metadata_context context,
- grpc_credentials_metadata_cb cb, void *user_data) {
+ grpc_credentials_mdelem_array *md_array, grpc_closure *on_request_metadata,
+ grpc_error **error) {
grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)creds;
-
+ grpc_credentials_mdelem_array_add(md_array, c->md);
if (c->is_async) {
- grpc_credentials_metadata_request *cb_arg =
- grpc_credentials_metadata_request_create(creds, cb, user_data);
- GRPC_CLOSURE_SCHED(exec_ctx,
- GRPC_CLOSURE_CREATE(on_simulated_token_fetch_done,
- cb_arg, grpc_executor_scheduler),
- GRPC_ERROR_NONE);
- } else {
- cb(exec_ctx, user_data, c->md_store->entries, 1, GRPC_CREDENTIALS_OK, NULL);
+ GRPC_CLOSURE_SCHED(exec_ctx, on_request_metadata, GRPC_ERROR_NONE);
+ return false;
}
+ return true;
+}
+
+static void md_only_test_cancel_get_request_metadata(
+ grpc_exec_ctx *exec_ctx, grpc_call_credentials *c,
+ grpc_credentials_mdelem_array *md_array, grpc_error *error) {
+ GRPC_ERROR_UNREF(error);
}
static grpc_call_credentials_vtable md_only_test_vtable = {
- md_only_test_destruct, md_only_test_get_request_metadata};
+ md_only_test_destruct, md_only_test_get_request_metadata,
+ md_only_test_cancel_get_request_metadata};
grpc_call_credentials *grpc_md_only_test_credentials_create(
- const char *md_key, const char *md_value, int is_async) {
+ grpc_exec_ctx *exec_ctx, const char *md_key, const char *md_value,
+ bool is_async) {
grpc_md_only_test_credentials *c =
gpr_zalloc(sizeof(grpc_md_only_test_credentials));
c->base.type = GRPC_CALL_CREDENTIALS_TYPE_OAUTH2;
c->base.vtable = &md_only_test_vtable;
gpr_ref_init(&c->base.refcount, 1);
- c->md_store = grpc_credentials_md_store_create(1);
- grpc_credentials_md_store_add_cstrings(c->md_store, md_key, md_value);
+ c->md =
+ grpc_mdelem_from_slices(exec_ctx, grpc_slice_from_copied_string(md_key),
+ grpc_slice_from_copied_string(md_value));
c->is_async = is_async;
return &c->base;
}
diff --git a/src/core/lib/security/credentials/fake/fake_credentials.h b/src/core/lib/security/credentials/fake/fake_credentials.h
index fae7a6a9c4..aa0f3b6e20 100644
--- a/src/core/lib/security/credentials/fake/fake_credentials.h
+++ b/src/core/lib/security/credentials/fake/fake_credentials.h
@@ -52,8 +52,8 @@ const char *grpc_fake_transport_get_expected_targets(
typedef struct {
grpc_call_credentials base;
- grpc_credentials_md_store *md_store;
- int is_async;
+ grpc_mdelem md;
+ bool is_async;
} grpc_md_only_test_credentials;
#endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_FAKE_FAKE_CREDENTIALS_H */
diff --git a/src/core/lib/security/credentials/iam/iam_credentials.c b/src/core/lib/security/credentials/iam/iam_credentials.c
index 4b32c5a047..3de8319d98 100644
--- a/src/core/lib/security/credentials/iam/iam_credentials.c
+++ b/src/core/lib/security/credentials/iam/iam_credentials.c
@@ -30,26 +30,33 @@
static void iam_destruct(grpc_exec_ctx *exec_ctx,
grpc_call_credentials *creds) {
grpc_google_iam_credentials *c = (grpc_google_iam_credentials *)creds;
- grpc_credentials_md_store_unref(exec_ctx, c->iam_md);
+ grpc_credentials_mdelem_array_destroy(exec_ctx, &c->md_array);
}
-static void iam_get_request_metadata(grpc_exec_ctx *exec_ctx,
+static bool iam_get_request_metadata(grpc_exec_ctx *exec_ctx,
grpc_call_credentials *creds,
grpc_polling_entity *pollent,
grpc_auth_metadata_context context,
- grpc_credentials_metadata_cb cb,
- void *user_data) {
+ grpc_credentials_mdelem_array *md_array,
+ grpc_closure *on_request_metadata,
+ grpc_error **error) {
grpc_google_iam_credentials *c = (grpc_google_iam_credentials *)creds;
- cb(exec_ctx, user_data, c->iam_md->entries, c->iam_md->num_entries,
- GRPC_CREDENTIALS_OK, NULL);
+ grpc_credentials_mdelem_array_append(md_array, &c->md_array);
+ return true;
}
-static grpc_call_credentials_vtable iam_vtable = {iam_destruct,
- iam_get_request_metadata};
+static void iam_cancel_get_request_metadata(
+ grpc_exec_ctx *exec_ctx, grpc_call_credentials *c,
+ grpc_credentials_mdelem_array *md_array, grpc_error *error) {
+ GRPC_ERROR_UNREF(error);
+}
+
+static grpc_call_credentials_vtable iam_vtable = {
+ iam_destruct, iam_get_request_metadata, iam_cancel_get_request_metadata};
grpc_call_credentials *grpc_google_iam_credentials_create(
const char *token, const char *authority_selector, void *reserved) {
- grpc_google_iam_credentials *c;
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
GRPC_API_TRACE(
"grpc_iam_credentials_create(token=%s, authority_selector=%s, "
"reserved=%p)",
@@ -57,14 +64,22 @@ grpc_call_credentials *grpc_google_iam_credentials_create(
GPR_ASSERT(reserved == NULL);
GPR_ASSERT(token != NULL);
GPR_ASSERT(authority_selector != NULL);
- c = gpr_zalloc(sizeof(grpc_google_iam_credentials));
+ grpc_google_iam_credentials *c = gpr_zalloc(sizeof(*c));
c->base.type = GRPC_CALL_CREDENTIALS_TYPE_IAM;
c->base.vtable = &iam_vtable;
gpr_ref_init(&c->base.refcount, 1);
- c->iam_md = grpc_credentials_md_store_create(2);
- grpc_credentials_md_store_add_cstrings(
- c->iam_md, GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY, token);
- grpc_credentials_md_store_add_cstrings(
- c->iam_md, GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, authority_selector);
+ grpc_mdelem md = grpc_mdelem_from_slices(
+ &exec_ctx,
+ grpc_slice_from_static_string(GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY),
+ grpc_slice_from_copied_string(token));
+ grpc_credentials_mdelem_array_add(&c->md_array, md);
+ GRPC_MDELEM_UNREF(&exec_ctx, md);
+ md = grpc_mdelem_from_slices(
+ &exec_ctx,
+ grpc_slice_from_static_string(GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY),
+ grpc_slice_from_copied_string(authority_selector));
+ grpc_credentials_mdelem_array_add(&c->md_array, md);
+ GRPC_MDELEM_UNREF(&exec_ctx, md);
+ grpc_exec_ctx_finish(&exec_ctx);
return &c->base;
}
diff --git a/src/core/lib/security/credentials/iam/iam_credentials.h b/src/core/lib/security/credentials/iam/iam_credentials.h
index fff3c6d2ca..5e3cf65bad 100644
--- a/src/core/lib/security/credentials/iam/iam_credentials.h
+++ b/src/core/lib/security/credentials/iam/iam_credentials.h
@@ -23,7 +23,7 @@
typedef struct {
grpc_call_credentials base;
- grpc_credentials_md_store *iam_md;
+ grpc_credentials_mdelem_array md_array;
} grpc_google_iam_credentials;
#endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_IAM_IAM_CREDENTIALS_H */
diff --git a/src/core/lib/security/credentials/jwt/jwt_credentials.c b/src/core/lib/security/credentials/jwt/jwt_credentials.c
index 4357657def..02c82e99ba 100644
--- a/src/core/lib/security/credentials/jwt/jwt_credentials.c
+++ b/src/core/lib/security/credentials/jwt/jwt_credentials.c
@@ -29,10 +29,8 @@
static void jwt_reset_cache(grpc_exec_ctx *exec_ctx,
grpc_service_account_jwt_access_credentials *c) {
- if (c->cached.jwt_md != NULL) {
- grpc_credentials_md_store_unref(exec_ctx, c->cached.jwt_md);
- c->cached.jwt_md = NULL;
- }
+ GRPC_MDELEM_UNREF(exec_ctx, c->cached.jwt_md);
+ c->cached.jwt_md = GRPC_MDNULL;
if (c->cached.service_url != NULL) {
gpr_free(c->cached.service_url);
c->cached.service_url = NULL;
@@ -49,33 +47,34 @@ static void jwt_destruct(grpc_exec_ctx *exec_ctx,
gpr_mu_destroy(&c->cache_mu);
}
-static void jwt_get_request_metadata(grpc_exec_ctx *exec_ctx,
+static bool jwt_get_request_metadata(grpc_exec_ctx *exec_ctx,
grpc_call_credentials *creds,
grpc_polling_entity *pollent,
grpc_auth_metadata_context context,
- grpc_credentials_metadata_cb cb,
- void *user_data) {
+ grpc_credentials_mdelem_array *md_array,
+ grpc_closure *on_request_metadata,
+ grpc_error **error) {
grpc_service_account_jwt_access_credentials *c =
(grpc_service_account_jwt_access_credentials *)creds;
gpr_timespec refresh_threshold = gpr_time_from_seconds(
GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS, GPR_TIMESPAN);
/* See if we can return a cached jwt. */
- grpc_credentials_md_store *jwt_md = NULL;
+ grpc_mdelem jwt_md = GRPC_MDNULL;
{
gpr_mu_lock(&c->cache_mu);
if (c->cached.service_url != NULL &&
strcmp(c->cached.service_url, context.service_url) == 0 &&
- c->cached.jwt_md != NULL &&
+ !GRPC_MDISNULL(c->cached.jwt_md) &&
(gpr_time_cmp(gpr_time_sub(c->cached.jwt_expiration,
gpr_now(GPR_CLOCK_REALTIME)),
refresh_threshold) > 0)) {
- jwt_md = grpc_credentials_md_store_ref(c->cached.jwt_md);
+ jwt_md = GRPC_MDELEM_REF(c->cached.jwt_md);
}
gpr_mu_unlock(&c->cache_mu);
}
- if (jwt_md == NULL) {
+ if (GRPC_MDISNULL(jwt_md)) {
char *jwt = NULL;
/* Generate a new jwt. */
gpr_mu_lock(&c->cache_mu);
@@ -89,27 +88,33 @@ static void jwt_get_request_metadata(grpc_exec_ctx *exec_ctx,
c->cached.jwt_expiration =
gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), c->jwt_lifetime);
c->cached.service_url = gpr_strdup(context.service_url);
- c->cached.jwt_md = grpc_credentials_md_store_create(1);
- grpc_credentials_md_store_add_cstrings(
- c->cached.jwt_md, GRPC_AUTHORIZATION_METADATA_KEY, md_value);
+ c->cached.jwt_md = grpc_mdelem_from_slices(
+ exec_ctx,
+ grpc_slice_from_static_string(GRPC_AUTHORIZATION_METADATA_KEY),
+ grpc_slice_from_copied_string(md_value));
gpr_free(md_value);
- jwt_md = grpc_credentials_md_store_ref(c->cached.jwt_md);
+ jwt_md = GRPC_MDELEM_REF(c->cached.jwt_md);
}
gpr_mu_unlock(&c->cache_mu);
}
- if (jwt_md != NULL) {
- cb(exec_ctx, user_data, jwt_md->entries, jwt_md->num_entries,
- GRPC_CREDENTIALS_OK, NULL);
- grpc_credentials_md_store_unref(exec_ctx, jwt_md);
+ if (!GRPC_MDISNULL(jwt_md)) {
+ grpc_credentials_mdelem_array_add(md_array, jwt_md);
+ GRPC_MDELEM_UNREF(exec_ctx, jwt_md);
} else {
- cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_ERROR,
- "Could not generate JWT.");
+ *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Could not generate JWT.");
}
+ return true;
+}
+
+static void jwt_cancel_get_request_metadata(
+ grpc_exec_ctx *exec_ctx, grpc_call_credentials *c,
+ grpc_credentials_mdelem_array *md_array, grpc_error *error) {
+ GRPC_ERROR_UNREF(error);
}
-static grpc_call_credentials_vtable jwt_vtable = {jwt_destruct,
- jwt_get_request_metadata};
+static grpc_call_credentials_vtable jwt_vtable = {
+ jwt_destruct, jwt_get_request_metadata, jwt_cancel_get_request_metadata};
grpc_call_credentials *
grpc_service_account_jwt_access_credentials_create_from_auth_json_key(
diff --git a/src/core/lib/security/credentials/jwt/jwt_credentials.h b/src/core/lib/security/credentials/jwt/jwt_credentials.h
index 6e461f1715..07f4022669 100644
--- a/src/core/lib/security/credentials/jwt/jwt_credentials.h
+++ b/src/core/lib/security/credentials/jwt/jwt_credentials.h
@@ -29,7 +29,7 @@ typedef struct {
// the service_url for a more sophisticated one.
gpr_mu cache_mu;
struct {
- grpc_credentials_md_store *jwt_md;
+ grpc_mdelem jwt_md;
char *service_url;
gpr_timespec jwt_expiration;
} cached;
diff --git a/src/core/lib/security/credentials/jwt/jwt_verifier.c b/src/core/lib/security/credentials/jwt/jwt_verifier.c
index 6cd558d123..a27284bc50 100644
--- a/src/core/lib/security/credentials/jwt/jwt_verifier.c
+++ b/src/core/lib/security/credentials/jwt/jwt_verifier.c
@@ -442,7 +442,7 @@ static EVP_PKEY *extract_pkey_from_x509(const char *x509_str) {
end:
BIO_free(bio);
- if (x509 != NULL) X509_free(x509);
+ X509_free(x509);
return result;
}
@@ -496,6 +496,8 @@ static EVP_PKEY *pkey_from_jwk(grpc_exec_ctx *exec_ctx, const grpc_json *json,
const grpc_json *key_prop;
RSA *rsa = NULL;
EVP_PKEY *result = NULL;
+ BIGNUM *tmp_n = NULL;
+ BIGNUM *tmp_e = NULL;
GPR_ASSERT(kty != NULL && json != NULL);
if (strcmp(kty, "RSA") != 0) {
@@ -507,8 +509,6 @@ static EVP_PKEY *pkey_from_jwk(grpc_exec_ctx *exec_ctx, const grpc_json *json,
gpr_log(GPR_ERROR, "Could not create rsa key.");
goto end;
}
- BIGNUM *tmp_n = NULL;
- BIGNUM *tmp_e = NULL;
for (key_prop = json->child; key_prop != NULL; key_prop = key_prop->next) {
if (strcmp(key_prop->key, "n") == 0) {
tmp_n =
@@ -528,11 +528,16 @@ static EVP_PKEY *pkey_from_jwk(grpc_exec_ctx *exec_ctx, const grpc_json *json,
gpr_log(GPR_ERROR, "Cannot set RSA key from inputs.");
goto end;
}
+ /* RSA_set0_key takes ownership on success. */
+ tmp_n = NULL;
+ tmp_e = NULL;
result = EVP_PKEY_new();
EVP_PKEY_set1_RSA(result, rsa); /* uprefs rsa. */
end:
- if (rsa != NULL) RSA_free(rsa);
+ RSA_free(rsa);
+ BN_free(tmp_n);
+ BN_free(tmp_e);
return result;
}
@@ -618,7 +623,7 @@ static int verify_jwt_signature(EVP_PKEY *key, const char *alg,
result = 1;
end:
- if (md_ctx != NULL) EVP_MD_CTX_destroy(md_ctx);
+ EVP_MD_CTX_destroy(md_ctx);
return result;
}
@@ -658,7 +663,7 @@ static void on_keys_retrieved(grpc_exec_ctx *exec_ctx, void *user_data,
end:
if (json != NULL) grpc_json_destroy(json);
- if (verification_key != NULL) EVP_PKEY_free(verification_key);
+ EVP_PKEY_free(verification_key);
ctx->user_cb(exec_ctx, ctx->user_data, status, claims);
verifier_cb_ctx_destroy(exec_ctx, ctx);
}
diff --git a/src/core/lib/security/credentials/oauth2/oauth2_credentials.c b/src/core/lib/security/credentials/oauth2/oauth2_credentials.c
index 9de561b310..10b270c49c 100644
--- a/src/core/lib/security/credentials/oauth2/oauth2_credentials.c
+++ b/src/core/lib/security/credentials/oauth2/oauth2_credentials.c
@@ -107,15 +107,17 @@ static void oauth2_token_fetcher_destruct(grpc_exec_ctx *exec_ctx,
grpc_call_credentials *creds) {
grpc_oauth2_token_fetcher_credentials *c =
(grpc_oauth2_token_fetcher_credentials *)creds;
- grpc_credentials_md_store_unref(exec_ctx, c->access_token_md);
+ GRPC_MDELEM_UNREF(exec_ctx, c->access_token_md);
gpr_mu_destroy(&c->mu);
+ grpc_pollset_set_destroy(exec_ctx,
+ grpc_polling_entity_pollset_set(&c->pollent));
grpc_httpcli_context_destroy(exec_ctx, &c->httpcli_context);
}
grpc_credentials_status
grpc_oauth2_token_fetcher_credentials_parse_server_response(
grpc_exec_ctx *exec_ctx, const grpc_http_response *response,
- grpc_credentials_md_store **token_md, gpr_timespec *token_lifetime) {
+ grpc_mdelem *token_md, gpr_timespec *token_lifetime) {
char *null_terminated_body = NULL;
char *new_access_token = NULL;
grpc_credentials_status status = GRPC_CREDENTIALS_OK;
@@ -184,17 +186,18 @@ grpc_oauth2_token_fetcher_credentials_parse_server_response(
token_lifetime->tv_sec = strtol(expires_in->value, NULL, 10);
token_lifetime->tv_nsec = 0;
token_lifetime->clock_type = GPR_TIMESPAN;
- if (*token_md != NULL) grpc_credentials_md_store_unref(exec_ctx, *token_md);
- *token_md = grpc_credentials_md_store_create(1);
- grpc_credentials_md_store_add_cstrings(
- *token_md, GRPC_AUTHORIZATION_METADATA_KEY, new_access_token);
+ if (!GRPC_MDISNULL(*token_md)) GRPC_MDELEM_UNREF(exec_ctx, *token_md);
+ *token_md = grpc_mdelem_from_slices(
+ exec_ctx,
+ grpc_slice_from_static_string(GRPC_AUTHORIZATION_METADATA_KEY),
+ grpc_slice_from_copied_string(new_access_token));
status = GRPC_CREDENTIALS_OK;
}
end:
- if (status != GRPC_CREDENTIALS_OK && (*token_md != NULL)) {
- grpc_credentials_md_store_unref(exec_ctx, *token_md);
- *token_md = NULL;
+ if (status != GRPC_CREDENTIALS_OK && !GRPC_MDISNULL(*token_md)) {
+ GRPC_MDELEM_UNREF(exec_ctx, *token_md);
+ *token_md = GRPC_MDNULL;
}
if (null_terminated_body != NULL) gpr_free(null_terminated_body);
if (new_access_token != NULL) gpr_free(new_access_token);
@@ -205,63 +208,130 @@ end:
static void on_oauth2_token_fetcher_http_response(grpc_exec_ctx *exec_ctx,
void *user_data,
grpc_error *error) {
+ GRPC_LOG_IF_ERROR("oauth_fetch", GRPC_ERROR_REF(error));
grpc_credentials_metadata_request *r =
(grpc_credentials_metadata_request *)user_data;
grpc_oauth2_token_fetcher_credentials *c =
(grpc_oauth2_token_fetcher_credentials *)r->creds;
+ grpc_mdelem access_token_md = GRPC_MDNULL;
gpr_timespec token_lifetime;
- grpc_credentials_status status;
-
- GRPC_LOG_IF_ERROR("oauth_fetch", GRPC_ERROR_REF(error));
-
+ grpc_credentials_status status =
+ grpc_oauth2_token_fetcher_credentials_parse_server_response(
+ exec_ctx, &r->response, &access_token_md, &token_lifetime);
+ // Update cache and grab list of pending requests.
gpr_mu_lock(&c->mu);
- status = grpc_oauth2_token_fetcher_credentials_parse_server_response(
- exec_ctx, &r->response, &c->access_token_md, &token_lifetime);
- if (status == GRPC_CREDENTIALS_OK) {
- c->token_expiration =
- gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), token_lifetime);
- r->cb(exec_ctx, r->user_data, c->access_token_md->entries,
- c->access_token_md->num_entries, GRPC_CREDENTIALS_OK, NULL);
- } else {
- c->token_expiration = gpr_inf_past(GPR_CLOCK_REALTIME);
- r->cb(exec_ctx, r->user_data, NULL, 0, status,
- "Error occured when fetching oauth2 token.");
- }
+ c->token_fetch_pending = false;
+ c->access_token_md = GRPC_MDELEM_REF(access_token_md);
+ c->token_expiration =
+ status == GRPC_CREDENTIALS_OK
+ ? gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), token_lifetime)
+ : gpr_inf_past(GPR_CLOCK_REALTIME);
+ grpc_oauth2_pending_get_request_metadata *pending_request =
+ c->pending_requests;
+ c->pending_requests = NULL;
gpr_mu_unlock(&c->mu);
+ // Invoke callbacks for all pending requests.
+ while (pending_request != NULL) {
+ if (status == GRPC_CREDENTIALS_OK) {
+ grpc_credentials_mdelem_array_add(pending_request->md_array,
+ access_token_md);
+ } else {
+ error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
+ "Error occured when fetching oauth2 token.", &error, 1);
+ }
+ GRPC_CLOSURE_SCHED(exec_ctx, pending_request->on_request_metadata, error);
+ grpc_polling_entity_del_from_pollset_set(
+ exec_ctx, pending_request->pollent,
+ grpc_polling_entity_pollset_set(&c->pollent));
+ grpc_oauth2_pending_get_request_metadata *prev = pending_request;
+ pending_request = pending_request->next;
+ gpr_free(prev);
+ }
+ GRPC_MDELEM_UNREF(exec_ctx, access_token_md);
+ grpc_call_credentials_unref(exec_ctx, r->creds);
grpc_credentials_metadata_request_destroy(exec_ctx, r);
}
-static void oauth2_token_fetcher_get_request_metadata(
+static bool oauth2_token_fetcher_get_request_metadata(
grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
grpc_polling_entity *pollent, grpc_auth_metadata_context context,
- grpc_credentials_metadata_cb cb, void *user_data) {
+ grpc_credentials_mdelem_array *md_array, grpc_closure *on_request_metadata,
+ grpc_error **error) {
grpc_oauth2_token_fetcher_credentials *c =
(grpc_oauth2_token_fetcher_credentials *)creds;
+ // Check if we can use the cached token.
gpr_timespec refresh_threshold = gpr_time_from_seconds(
GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS, GPR_TIMESPAN);
- grpc_credentials_md_store *cached_access_token_md = NULL;
- {
- gpr_mu_lock(&c->mu);
- if (c->access_token_md != NULL &&
- (gpr_time_cmp(
- gpr_time_sub(c->token_expiration, gpr_now(GPR_CLOCK_REALTIME)),
- refresh_threshold) > 0)) {
- cached_access_token_md =
- grpc_credentials_md_store_ref(c->access_token_md);
- }
+ grpc_mdelem cached_access_token_md = GRPC_MDNULL;
+ gpr_mu_lock(&c->mu);
+ if (!GRPC_MDISNULL(c->access_token_md) &&
+ (gpr_time_cmp(
+ gpr_time_sub(c->token_expiration, gpr_now(GPR_CLOCK_REALTIME)),
+ refresh_threshold) > 0)) {
+ cached_access_token_md = GRPC_MDELEM_REF(c->access_token_md);
+ }
+ if (!GRPC_MDISNULL(cached_access_token_md)) {
gpr_mu_unlock(&c->mu);
+ grpc_credentials_mdelem_array_add(md_array, cached_access_token_md);
+ GRPC_MDELEM_UNREF(exec_ctx, cached_access_token_md);
+ return true;
}
- if (cached_access_token_md != NULL) {
- cb(exec_ctx, user_data, cached_access_token_md->entries,
- cached_access_token_md->num_entries, GRPC_CREDENTIALS_OK, NULL);
- grpc_credentials_md_store_unref(exec_ctx, cached_access_token_md);
- } else {
+ // Couldn't get the token from the cache.
+ // Add request to c->pending_requests and start a new fetch if needed.
+ grpc_oauth2_pending_get_request_metadata *pending_request =
+ (grpc_oauth2_pending_get_request_metadata *)gpr_malloc(
+ sizeof(*pending_request));
+ pending_request->md_array = md_array;
+ pending_request->on_request_metadata = on_request_metadata;
+ pending_request->pollent = pollent;
+ grpc_polling_entity_add_to_pollset_set(
+ exec_ctx, pollent, grpc_polling_entity_pollset_set(&c->pollent));
+ pending_request->next = c->pending_requests;
+ c->pending_requests = pending_request;
+ bool start_fetch = false;
+ if (!c->token_fetch_pending) {
+ c->token_fetch_pending = true;
+ start_fetch = true;
+ }
+ gpr_mu_unlock(&c->mu);
+ if (start_fetch) {
+ grpc_call_credentials_ref(creds);
c->fetch_func(
- exec_ctx,
- grpc_credentials_metadata_request_create(creds, cb, user_data),
- &c->httpcli_context, pollent, on_oauth2_token_fetcher_http_response,
- gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), refresh_threshold));
+ exec_ctx, grpc_credentials_metadata_request_create(creds),
+ &c->httpcli_context, &c->pollent, on_oauth2_token_fetcher_http_response,
+ gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), refresh_threshold));
}
+ return false;
+}
+
+static void oauth2_token_fetcher_cancel_get_request_metadata(
+ grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
+ grpc_credentials_mdelem_array *md_array, grpc_error *error) {
+ grpc_oauth2_token_fetcher_credentials *c =
+ (grpc_oauth2_token_fetcher_credentials *)creds;
+ gpr_mu_lock(&c->mu);
+ grpc_oauth2_pending_get_request_metadata *prev = NULL;
+ grpc_oauth2_pending_get_request_metadata *pending_request =
+ c->pending_requests;
+ while (pending_request != NULL) {
+ if (pending_request->md_array == md_array) {
+ // Remove matching pending request from the list.
+ if (prev != NULL) {
+ prev->next = pending_request->next;
+ } else {
+ c->pending_requests = pending_request->next;
+ }
+ // Invoke the callback immediately with an error.
+ GRPC_CLOSURE_SCHED(exec_ctx, pending_request->on_request_metadata,
+ GRPC_ERROR_REF(error));
+ gpr_free(pending_request);
+ break;
+ }
+ prev = pending_request;
+ pending_request = pending_request->next;
+ }
+ gpr_mu_unlock(&c->mu);
+ GRPC_ERROR_UNREF(error);
}
static void init_oauth2_token_fetcher(grpc_oauth2_token_fetcher_credentials *c,
@@ -272,6 +342,8 @@ static void init_oauth2_token_fetcher(grpc_oauth2_token_fetcher_credentials *c,
gpr_mu_init(&c->mu);
c->token_expiration = gpr_inf_past(GPR_CLOCK_REALTIME);
c->fetch_func = fetch_func;
+ c->pollent =
+ grpc_polling_entity_create_from_pollset_set(grpc_pollset_set_create());
grpc_httpcli_context_init(&c->httpcli_context);
}
@@ -280,7 +352,8 @@ static void init_oauth2_token_fetcher(grpc_oauth2_token_fetcher_credentials *c,
//
static grpc_call_credentials_vtable compute_engine_vtable = {
- oauth2_token_fetcher_destruct, oauth2_token_fetcher_get_request_metadata};
+ oauth2_token_fetcher_destruct, oauth2_token_fetcher_get_request_metadata,
+ oauth2_token_fetcher_cancel_get_request_metadata};
static void compute_engine_fetch_oauth2(
grpc_exec_ctx *exec_ctx, grpc_credentials_metadata_request *metadata_req,
@@ -301,7 +374,6 @@ static void compute_engine_fetch_oauth2(
grpc_httpcli_get(
exec_ctx, httpcli_context, pollent, resource_quota, &request, deadline,
GRPC_CLOSURE_CREATE(response_cb, metadata_req, grpc_schedule_on_exec_ctx),
-
&metadata_req->response);
grpc_resource_quota_unref_internal(exec_ctx, resource_quota);
}
@@ -331,7 +403,8 @@ static void refresh_token_destruct(grpc_exec_ctx *exec_ctx,
}
static grpc_call_credentials_vtable refresh_token_vtable = {
- refresh_token_destruct, oauth2_token_fetcher_get_request_metadata};
+ refresh_token_destruct, oauth2_token_fetcher_get_request_metadata,
+ oauth2_token_fetcher_cancel_get_request_metadata};
static void refresh_token_fetch_oauth2(
grpc_exec_ctx *exec_ctx, grpc_credentials_metadata_request *metadata_req,
@@ -416,26 +489,33 @@ grpc_call_credentials *grpc_google_refresh_token_credentials_create(
static void access_token_destruct(grpc_exec_ctx *exec_ctx,
grpc_call_credentials *creds) {
grpc_access_token_credentials *c = (grpc_access_token_credentials *)creds;
- grpc_credentials_md_store_unref(exec_ctx, c->access_token_md);
+ GRPC_MDELEM_UNREF(exec_ctx, c->access_token_md);
}
-static void access_token_get_request_metadata(
+static bool access_token_get_request_metadata(
grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
grpc_polling_entity *pollent, grpc_auth_metadata_context context,
- grpc_credentials_metadata_cb cb, void *user_data) {
+ grpc_credentials_mdelem_array *md_array, grpc_closure *on_request_metadata,
+ grpc_error **error) {
grpc_access_token_credentials *c = (grpc_access_token_credentials *)creds;
- cb(exec_ctx, user_data, c->access_token_md->entries, 1, GRPC_CREDENTIALS_OK,
- NULL);
+ grpc_credentials_mdelem_array_add(md_array, c->access_token_md);
+ return true;
+}
+
+static void access_token_cancel_get_request_metadata(
+ grpc_exec_ctx *exec_ctx, grpc_call_credentials *c,
+ grpc_credentials_mdelem_array *md_array, grpc_error *error) {
+ GRPC_ERROR_UNREF(error);
}
static grpc_call_credentials_vtable access_token_vtable = {
- access_token_destruct, access_token_get_request_metadata};
+ access_token_destruct, access_token_get_request_metadata,
+ access_token_cancel_get_request_metadata};
grpc_call_credentials *grpc_access_token_credentials_create(
const char *access_token, void *reserved) {
grpc_access_token_credentials *c =
gpr_zalloc(sizeof(grpc_access_token_credentials));
- char *token_md_value;
GRPC_API_TRACE(
"grpc_access_token_credentials_create(access_token=<redacted>, "
"reserved=%p)",
@@ -444,10 +524,13 @@ grpc_call_credentials *grpc_access_token_credentials_create(
c->base.type = GRPC_CALL_CREDENTIALS_TYPE_OAUTH2;
c->base.vtable = &access_token_vtable;
gpr_ref_init(&c->base.refcount, 1);
- c->access_token_md = grpc_credentials_md_store_create(1);
+ char *token_md_value;
gpr_asprintf(&token_md_value, "Bearer %s", access_token);
- grpc_credentials_md_store_add_cstrings(
- c->access_token_md, GRPC_AUTHORIZATION_METADATA_KEY, token_md_value);
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+ c->access_token_md = grpc_mdelem_from_slices(
+ &exec_ctx, grpc_slice_from_static_string(GRPC_AUTHORIZATION_METADATA_KEY),
+ grpc_slice_from_copied_string(token_md_value));
+ grpc_exec_ctx_finish(&exec_ctx);
gpr_free(token_md_value);
return &c->base;
}
diff --git a/src/core/lib/security/credentials/oauth2/oauth2_credentials.h b/src/core/lib/security/credentials/oauth2/oauth2_credentials.h
index 72093afe9e..d9ad6691b8 100644
--- a/src/core/lib/security/credentials/oauth2/oauth2_credentials.h
+++ b/src/core/lib/security/credentials/oauth2/oauth2_credentials.h
@@ -58,13 +58,24 @@ typedef void (*grpc_fetch_oauth2_func)(grpc_exec_ctx *exec_ctx,
grpc_polling_entity *pollent,
grpc_iomgr_cb_func cb,
gpr_timespec deadline);
+
+typedef struct grpc_oauth2_pending_get_request_metadata {
+ grpc_credentials_mdelem_array *md_array;
+ grpc_closure *on_request_metadata;
+ grpc_polling_entity *pollent;
+ struct grpc_oauth2_pending_get_request_metadata *next;
+} grpc_oauth2_pending_get_request_metadata;
+
typedef struct {
grpc_call_credentials base;
gpr_mu mu;
- grpc_credentials_md_store *access_token_md;
+ grpc_mdelem access_token_md;
gpr_timespec token_expiration;
+ bool token_fetch_pending;
+ grpc_oauth2_pending_get_request_metadata *pending_requests;
grpc_httpcli_context httpcli_context;
grpc_fetch_oauth2_func fetch_func;
+ grpc_polling_entity pollent;
} grpc_oauth2_token_fetcher_credentials;
// Google refresh token credentials.
@@ -76,7 +87,7 @@ typedef struct {
// Access token credentials.
typedef struct {
grpc_call_credentials base;
- grpc_credentials_md_store *access_token_md;
+ grpc_mdelem access_token_md;
} grpc_access_token_credentials;
// Private constructor for refresh token credentials from an already parsed
@@ -89,6 +100,6 @@ grpc_refresh_token_credentials_create_from_auth_refresh_token(
grpc_credentials_status
grpc_oauth2_token_fetcher_credentials_parse_server_response(
grpc_exec_ctx *exec_ctx, const struct grpc_http_response *response,
- grpc_credentials_md_store **token_md, gpr_timespec *token_lifetime);
+ grpc_mdelem *token_md, gpr_timespec *token_lifetime);
#endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_OAUTH2_OAUTH2_CREDENTIALS_H */
diff --git a/src/core/lib/security/credentials/plugin/plugin_credentials.c b/src/core/lib/security/credentials/plugin/plugin_credentials.c
index 96ebfb4d0d..73e0c23e0f 100644
--- a/src/core/lib/security/credentials/plugin/plugin_credentials.c
+++ b/src/core/lib/security/credentials/plugin/plugin_credentials.c
@@ -31,19 +31,28 @@
#include "src/core/lib/surface/api_trace.h"
#include "src/core/lib/surface/validate_metadata.h"
-typedef struct {
- void *user_data;
- grpc_credentials_metadata_cb cb;
-} grpc_metadata_plugin_request;
-
static void plugin_destruct(grpc_exec_ctx *exec_ctx,
grpc_call_credentials *creds) {
grpc_plugin_credentials *c = (grpc_plugin_credentials *)creds;
+ gpr_mu_destroy(&c->mu);
if (c->plugin.state != NULL && c->plugin.destroy != NULL) {
c->plugin.destroy(c->plugin.state);
}
}
+static void pending_request_remove_locked(
+ grpc_plugin_credentials *c,
+ grpc_plugin_credentials_pending_request *pending_request) {
+ if (pending_request->prev == NULL) {
+ c->pending_requests = pending_request->next;
+ } else {
+ pending_request->prev->next = pending_request->next;
+ }
+ if (pending_request->next != NULL) {
+ pending_request->next->prev = pending_request->prev;
+ }
+}
+
static void plugin_md_request_metadata_ready(void *request,
const grpc_metadata *md,
size_t num_md,
@@ -53,76 +62,117 @@ static void plugin_md_request_metadata_ready(void *request,
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INITIALIZER(
GRPC_EXEC_CTX_FLAG_IS_FINISHED | GRPC_EXEC_CTX_FLAG_THREAD_RESOURCE_LOOP,
NULL, NULL);
- grpc_metadata_plugin_request *r = (grpc_metadata_plugin_request *)request;
- if (status != GRPC_STATUS_OK) {
- if (error_details != NULL) {
- gpr_log(GPR_ERROR, "Getting metadata from plugin failed with error: %s",
- error_details);
- }
- r->cb(&exec_ctx, r->user_data, NULL, 0, GRPC_CREDENTIALS_ERROR,
- error_details);
- } else {
- size_t i;
- bool seen_illegal_header = false;
- grpc_credentials_md *md_array = NULL;
- for (i = 0; i < num_md; i++) {
- if (!GRPC_LOG_IF_ERROR("validate_metadata_from_plugin",
- grpc_validate_header_key_is_legal(md[i].key))) {
- seen_illegal_header = true;
- break;
- } else if (!grpc_is_binary_header(md[i].key) &&
- !GRPC_LOG_IF_ERROR(
- "validate_metadata_from_plugin",
- grpc_validate_header_nonbin_value_is_legal(md[i].value))) {
- gpr_log(GPR_ERROR, "Plugin added invalid metadata value.");
- seen_illegal_header = true;
- break;
+ grpc_plugin_credentials_pending_request *r =
+ (grpc_plugin_credentials_pending_request *)request;
+ // Check if the request has been cancelled.
+ // If not, remove it from the pending list, so that it cannot be
+ // cancelled out from under us.
+ gpr_mu_lock(&r->creds->mu);
+ if (!r->cancelled) pending_request_remove_locked(r->creds, r);
+ gpr_mu_unlock(&r->creds->mu);
+ grpc_call_credentials_unref(&exec_ctx, &r->creds->base);
+ // If it has not been cancelled, process it.
+ if (!r->cancelled) {
+ if (status != GRPC_STATUS_OK) {
+ char *msg;
+ gpr_asprintf(&msg, "Getting metadata from plugin failed with error: %s",
+ error_details);
+ GRPC_CLOSURE_SCHED(&exec_ctx, r->on_request_metadata,
+ GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg));
+ gpr_free(msg);
+ } else {
+ bool seen_illegal_header = false;
+ for (size_t i = 0; i < num_md; ++i) {
+ if (!GRPC_LOG_IF_ERROR("validate_metadata_from_plugin",
+ grpc_validate_header_key_is_legal(md[i].key))) {
+ seen_illegal_header = true;
+ break;
+ } else if (!grpc_is_binary_header(md[i].key) &&
+ !GRPC_LOG_IF_ERROR(
+ "validate_metadata_from_plugin",
+ grpc_validate_header_nonbin_value_is_legal(
+ md[i].value))) {
+ gpr_log(GPR_ERROR, "Plugin added invalid metadata value.");
+ seen_illegal_header = true;
+ break;
+ }
}
- }
- if (seen_illegal_header) {
- r->cb(&exec_ctx, r->user_data, NULL, 0, GRPC_CREDENTIALS_ERROR,
- "Illegal metadata");
- } else if (num_md > 0) {
- md_array = gpr_malloc(num_md * sizeof(grpc_credentials_md));
- for (i = 0; i < num_md; i++) {
- md_array[i].key = grpc_slice_ref_internal(md[i].key);
- md_array[i].value = grpc_slice_ref_internal(md[i].value);
+ if (seen_illegal_header) {
+ GRPC_CLOSURE_SCHED(
+ &exec_ctx, r->on_request_metadata,
+ GRPC_ERROR_CREATE_FROM_STATIC_STRING("Illegal metadata"));
+ } else {
+ for (size_t i = 0; i < num_md; ++i) {
+ grpc_mdelem mdelem = grpc_mdelem_from_slices(
+ &exec_ctx, grpc_slice_ref_internal(md[i].key),
+ grpc_slice_ref_internal(md[i].value));
+ grpc_credentials_mdelem_array_add(r->md_array, mdelem);
+ GRPC_MDELEM_UNREF(&exec_ctx, mdelem);
+ }
+ GRPC_CLOSURE_SCHED(&exec_ctx, r->on_request_metadata, GRPC_ERROR_NONE);
}
- r->cb(&exec_ctx, r->user_data, md_array, num_md, GRPC_CREDENTIALS_OK,
- NULL);
- for (i = 0; i < num_md; i++) {
- grpc_slice_unref_internal(&exec_ctx, md_array[i].key);
- grpc_slice_unref_internal(&exec_ctx, md_array[i].value);
- }
- gpr_free(md_array);
- } else if (num_md == 0) {
- r->cb(&exec_ctx, r->user_data, NULL, 0, GRPC_CREDENTIALS_OK, NULL);
}
}
gpr_free(r);
grpc_exec_ctx_finish(&exec_ctx);
}
-static void plugin_get_request_metadata(grpc_exec_ctx *exec_ctx,
+static bool plugin_get_request_metadata(grpc_exec_ctx *exec_ctx,
grpc_call_credentials *creds,
grpc_polling_entity *pollent,
grpc_auth_metadata_context context,
- grpc_credentials_metadata_cb cb,
- void *user_data) {
+ grpc_credentials_mdelem_array *md_array,
+ grpc_closure *on_request_metadata,
+ grpc_error **error) {
grpc_plugin_credentials *c = (grpc_plugin_credentials *)creds;
if (c->plugin.get_metadata != NULL) {
- grpc_metadata_plugin_request *request = gpr_zalloc(sizeof(*request));
- request->user_data = user_data;
- request->cb = cb;
+ // Create pending_request object.
+ grpc_plugin_credentials_pending_request *pending_request =
+ (grpc_plugin_credentials_pending_request *)gpr_zalloc(
+ sizeof(*pending_request));
+ pending_request->creds = c;
+ pending_request->md_array = md_array;
+ pending_request->on_request_metadata = on_request_metadata;
+ // Add it to the pending list.
+ gpr_mu_lock(&c->mu);
+ if (c->pending_requests != NULL) {
+ c->pending_requests->prev = pending_request;
+ }
+ pending_request->next = c->pending_requests;
+ c->pending_requests = pending_request;
+ gpr_mu_unlock(&c->mu);
+ // Invoke the plugin. The callback holds a ref to us.
+ grpc_call_credentials_ref(creds);
c->plugin.get_metadata(c->plugin.state, context,
- plugin_md_request_metadata_ready, request);
- } else {
- cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_OK, NULL);
+ plugin_md_request_metadata_ready, pending_request);
+ return false;
+ }
+ return true;
+}
+
+static void plugin_cancel_get_request_metadata(
+ grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
+ grpc_credentials_mdelem_array *md_array, grpc_error *error) {
+ grpc_plugin_credentials *c = (grpc_plugin_credentials *)creds;
+ gpr_mu_lock(&c->mu);
+ for (grpc_plugin_credentials_pending_request *pending_request =
+ c->pending_requests;
+ pending_request != NULL; pending_request = pending_request->next) {
+ if (pending_request->md_array == md_array) {
+ pending_request->cancelled = true;
+ GRPC_CLOSURE_SCHED(exec_ctx, pending_request->on_request_metadata,
+ GRPC_ERROR_REF(error));
+ pending_request_remove_locked(c, pending_request);
+ break;
+ }
}
+ gpr_mu_unlock(&c->mu);
+ GRPC_ERROR_UNREF(error);
}
static grpc_call_credentials_vtable plugin_vtable = {
- plugin_destruct, plugin_get_request_metadata};
+ plugin_destruct, plugin_get_request_metadata,
+ plugin_cancel_get_request_metadata};
grpc_call_credentials *grpc_metadata_credentials_create_from_plugin(
grpc_metadata_credentials_plugin plugin, void *reserved) {
@@ -134,5 +184,6 @@ grpc_call_credentials *grpc_metadata_credentials_create_from_plugin(
c->base.vtable = &plugin_vtable;
gpr_ref_init(&c->base.refcount, 1);
c->plugin = plugin;
+ gpr_mu_init(&c->mu);
return &c->base;
}
diff --git a/src/core/lib/security/credentials/plugin/plugin_credentials.h b/src/core/lib/security/credentials/plugin/plugin_credentials.h
index ba3dd76859..57266d589a 100644
--- a/src/core/lib/security/credentials/plugin/plugin_credentials.h
+++ b/src/core/lib/security/credentials/plugin/plugin_credentials.h
@@ -21,10 +21,22 @@
#include "src/core/lib/security/credentials/credentials.h"
-typedef struct {
+struct grpc_plugin_credentials;
+
+typedef struct grpc_plugin_credentials_pending_request {
+ bool cancelled;
+ struct grpc_plugin_credentials *creds;
+ grpc_credentials_mdelem_array *md_array;
+ grpc_closure *on_request_metadata;
+ struct grpc_plugin_credentials_pending_request *prev;
+ struct grpc_plugin_credentials_pending_request *next;
+} grpc_plugin_credentials_pending_request;
+
+typedef struct grpc_plugin_credentials {
grpc_call_credentials base;
grpc_metadata_credentials_plugin plugin;
- grpc_credentials_md_store *plugin_md;
+ gpr_mu mu;
+ grpc_plugin_credentials_pending_request *pending_requests;
} grpc_plugin_credentials;
#endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_PLUGIN_PLUGIN_CREDENTIALS_H */
diff --git a/src/core/lib/security/transport/client_auth_filter.c b/src/core/lib/security/transport/client_auth_filter.c
index 50a51b31cd..e3f0163a6c 100644
--- a/src/core/lib/security/transport/client_auth_filter.c
+++ b/src/core/lib/security/transport/client_auth_filter.c
@@ -39,6 +39,7 @@
/* We can have a per-call credentials. */
typedef struct {
+ grpc_call_combiner *call_combiner;
grpc_call_credentials *creds;
bool have_host;
bool have_method;
@@ -49,10 +50,11 @@ typedef struct {
pollset_set so that work can progress when this call wants work to progress
*/
grpc_polling_entity *pollent;
- gpr_atm security_context_set;
- gpr_mu security_context_mu;
+ grpc_credentials_mdelem_array md_array;
grpc_linked_mdelem md_links[MAX_CREDENTIALS_METADATA_COUNT];
grpc_auth_metadata_context auth_md_context;
+ grpc_closure async_cancel_closure;
+ grpc_closure async_result_closure;
} call_data;
/* We can have a per-channel credentials. */
@@ -86,42 +88,32 @@ static void add_error(grpc_error **combined, grpc_error *error) {
*combined = grpc_error_add_child(*combined, error);
}
-static void on_credentials_metadata(grpc_exec_ctx *exec_ctx, void *user_data,
- grpc_credentials_md *md_elems,
- size_t num_md,
- grpc_credentials_status status,
- const char *error_details) {
- grpc_transport_stream_op_batch *batch =
- (grpc_transport_stream_op_batch *)user_data;
+static void on_credentials_metadata(grpc_exec_ctx *exec_ctx, void *arg,
+ grpc_error *input_error) {
+ grpc_transport_stream_op_batch *batch = (grpc_transport_stream_op_batch *)arg;
grpc_call_element *elem = batch->handler_private.extra_arg;
call_data *calld = elem->call_data;
+ grpc_call_combiner_set_notify_on_cancel(exec_ctx, calld->call_combiner, NULL);
reset_auth_metadata_context(&calld->auth_md_context);
- grpc_error *error = GRPC_ERROR_NONE;
- if (status != GRPC_CREDENTIALS_OK) {
- error = grpc_error_set_int(
- GRPC_ERROR_CREATE_FROM_COPIED_STRING(
- error_details != NULL && strlen(error_details) > 0
- ? error_details
- : "Credentials failed to get metadata."),
- GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAUTHENTICATED);
- } else {
- GPR_ASSERT(num_md <= MAX_CREDENTIALS_METADATA_COUNT);
+ grpc_error *error = GRPC_ERROR_REF(input_error);
+ if (error == GRPC_ERROR_NONE) {
+ GPR_ASSERT(calld->md_array.size <= MAX_CREDENTIALS_METADATA_COUNT);
GPR_ASSERT(batch->send_initial_metadata);
grpc_metadata_batch *mdb =
batch->payload->send_initial_metadata.send_initial_metadata;
- for (size_t i = 0; i < num_md; i++) {
- add_error(&error,
- grpc_metadata_batch_add_tail(
- exec_ctx, mdb, &calld->md_links[i],
- grpc_mdelem_from_slices(
- exec_ctx, grpc_slice_ref_internal(md_elems[i].key),
- grpc_slice_ref_internal(md_elems[i].value))));
+ for (size_t i = 0; i < calld->md_array.size; ++i) {
+ add_error(&error, grpc_metadata_batch_add_tail(
+ exec_ctx, mdb, &calld->md_links[i],
+ GRPC_MDELEM_REF(calld->md_array.md[i])));
}
}
if (error == GRPC_ERROR_NONE) {
grpc_call_next_op(exec_ctx, elem, batch);
} else {
- grpc_transport_stream_op_batch_finish_with_failure(exec_ctx, batch, error);
+ error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS,
+ GRPC_STATUS_UNAUTHENTICATED);
+ grpc_transport_stream_op_batch_finish_with_failure(exec_ctx, batch, error,
+ calld->call_combiner);
}
}
@@ -155,6 +147,14 @@ void build_auth_metadata_context(grpc_security_connector *sc,
gpr_free(host);
}
+static void cancel_get_request_metadata(grpc_exec_ctx *exec_ctx, void *arg,
+ grpc_error *error) {
+ grpc_call_element *elem = (grpc_call_element *)arg;
+ call_data *calld = (call_data *)elem->call_data;
+ grpc_call_credentials_cancel_get_request_metadata(
+ exec_ctx, calld->creds, &calld->md_array, GRPC_ERROR_REF(error));
+}
+
static void send_security_metadata(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
grpc_transport_stream_op_batch *batch) {
@@ -183,7 +183,8 @@ static void send_security_metadata(grpc_exec_ctx *exec_ctx,
grpc_error_set_int(
GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Incompatible credentials set on channel and call."),
- GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAUTHENTICATED));
+ GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAUTHENTICATED),
+ calld->call_combiner);
return;
}
} else {
@@ -193,20 +194,34 @@ static void send_security_metadata(grpc_exec_ctx *exec_ctx,
build_auth_metadata_context(&chand->security_connector->base,
chand->auth_context, calld);
+
GPR_ASSERT(calld->pollent != NULL);
- grpc_call_credentials_get_request_metadata(
- exec_ctx, calld->creds, calld->pollent, calld->auth_md_context,
- on_credentials_metadata, batch);
+
+ GRPC_CLOSURE_INIT(&calld->async_result_closure, on_credentials_metadata,
+ batch, grpc_schedule_on_exec_ctx);
+ grpc_error *error = GRPC_ERROR_NONE;
+ if (grpc_call_credentials_get_request_metadata(
+ exec_ctx, calld->creds, calld->pollent, calld->auth_md_context,
+ &calld->md_array, &calld->async_result_closure, &error)) {
+ // Synchronous return; invoke on_credentials_metadata() directly.
+ on_credentials_metadata(exec_ctx, batch, error);
+ GRPC_ERROR_UNREF(error);
+ } else {
+ // Async return; register cancellation closure with call combiner.
+ GRPC_CLOSURE_INIT(&calld->async_cancel_closure, cancel_get_request_metadata,
+ elem, grpc_schedule_on_exec_ctx);
+ grpc_call_combiner_set_notify_on_cancel(exec_ctx, calld->call_combiner,
+ &calld->async_cancel_closure);
+ }
}
-static void on_host_checked(grpc_exec_ctx *exec_ctx, void *user_data,
- grpc_security_status status) {
- grpc_transport_stream_op_batch *batch =
- (grpc_transport_stream_op_batch *)user_data;
+static void on_host_checked(grpc_exec_ctx *exec_ctx, void *arg,
+ grpc_error *error) {
+ grpc_transport_stream_op_batch *batch = (grpc_transport_stream_op_batch *)arg;
grpc_call_element *elem = batch->handler_private.extra_arg;
call_data *calld = elem->call_data;
-
- if (status == GRPC_SECURITY_OK) {
+ grpc_call_combiner_set_notify_on_cancel(exec_ctx, calld->call_combiner, NULL);
+ if (error == GRPC_ERROR_NONE) {
send_security_metadata(exec_ctx, elem, batch);
} else {
char *error_msg;
@@ -218,11 +233,22 @@ static void on_host_checked(grpc_exec_ctx *exec_ctx, void *user_data,
exec_ctx, batch,
grpc_error_set_int(GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_msg),
GRPC_ERROR_INT_GRPC_STATUS,
- GRPC_STATUS_UNAUTHENTICATED));
+ GRPC_STATUS_UNAUTHENTICATED),
+ calld->call_combiner);
gpr_free(error_msg);
}
}
+static void cancel_check_call_host(grpc_exec_ctx *exec_ctx, void *arg,
+ grpc_error *error) {
+ grpc_call_element *elem = (grpc_call_element *)arg;
+ call_data *calld = (call_data *)elem->call_data;
+ channel_data *chand = (channel_data *)elem->channel_data;
+ grpc_channel_security_connector_cancel_check_call_host(
+ exec_ctx, chand->security_connector, &calld->async_result_closure,
+ GRPC_ERROR_REF(error));
+}
+
static void auth_start_transport_stream_op_batch(
grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
grpc_transport_stream_op_batch *batch) {
@@ -233,26 +259,18 @@ static void auth_start_transport_stream_op_batch(
channel_data *chand = elem->channel_data;
if (!batch->cancel_stream) {
- /* double checked lock over security context to ensure it's set once */
- if (gpr_atm_acq_load(&calld->security_context_set) == 0) {
- gpr_mu_lock(&calld->security_context_mu);
- if (gpr_atm_acq_load(&calld->security_context_set) == 0) {
- GPR_ASSERT(batch->payload->context != NULL);
- if (batch->payload->context[GRPC_CONTEXT_SECURITY].value == NULL) {
- batch->payload->context[GRPC_CONTEXT_SECURITY].value =
- grpc_client_security_context_create();
- batch->payload->context[GRPC_CONTEXT_SECURITY].destroy =
- grpc_client_security_context_destroy;
- }
- grpc_client_security_context *sec_ctx =
- batch->payload->context[GRPC_CONTEXT_SECURITY].value;
- GRPC_AUTH_CONTEXT_UNREF(sec_ctx->auth_context, "client auth filter");
- sec_ctx->auth_context =
- GRPC_AUTH_CONTEXT_REF(chand->auth_context, "client_auth_filter");
- gpr_atm_rel_store(&calld->security_context_set, 1);
- }
- gpr_mu_unlock(&calld->security_context_mu);
+ GPR_ASSERT(batch->payload->context != NULL);
+ if (batch->payload->context[GRPC_CONTEXT_SECURITY].value == NULL) {
+ batch->payload->context[GRPC_CONTEXT_SECURITY].value =
+ grpc_client_security_context_create();
+ batch->payload->context[GRPC_CONTEXT_SECURITY].destroy =
+ grpc_client_security_context_destroy;
}
+ grpc_client_security_context *sec_ctx =
+ batch->payload->context[GRPC_CONTEXT_SECURITY].value;
+ GRPC_AUTH_CONTEXT_UNREF(sec_ctx->auth_context, "client auth filter");
+ sec_ctx->auth_context =
+ GRPC_AUTH_CONTEXT_REF(chand->auth_context, "client_auth_filter");
}
if (batch->send_initial_metadata) {
@@ -277,11 +295,24 @@ static void auth_start_transport_stream_op_batch(
}
}
if (calld->have_host) {
- char *call_host = grpc_slice_to_c_string(calld->host);
batch->handler_private.extra_arg = elem;
- grpc_channel_security_connector_check_call_host(
- exec_ctx, chand->security_connector, call_host, chand->auth_context,
- on_host_checked, batch);
+ GRPC_CLOSURE_INIT(&calld->async_result_closure, on_host_checked, batch,
+ grpc_schedule_on_exec_ctx);
+ char *call_host = grpc_slice_to_c_string(calld->host);
+ grpc_error *error = GRPC_ERROR_NONE;
+ if (grpc_channel_security_connector_check_call_host(
+ exec_ctx, chand->security_connector, call_host,
+ chand->auth_context, &calld->async_result_closure, &error)) {
+ // Synchronous return; invoke on_host_checked() directly.
+ on_host_checked(exec_ctx, batch, error);
+ GRPC_ERROR_UNREF(error);
+ } else {
+ // Async return; register cancellation closure with call combiner.
+ GRPC_CLOSURE_INIT(&calld->async_cancel_closure, cancel_check_call_host,
+ elem, grpc_schedule_on_exec_ctx);
+ grpc_call_combiner_set_notify_on_cancel(exec_ctx, calld->call_combiner,
+ &calld->async_cancel_closure);
+ }
gpr_free(call_host);
GPR_TIMER_END("auth_start_transport_stream_op_batch", 0);
return; /* early exit */
@@ -298,8 +329,7 @@ static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
const grpc_call_element_args *args) {
call_data *calld = elem->call_data;
- memset(calld, 0, sizeof(*calld));
- gpr_mu_init(&calld->security_context_mu);
+ calld->call_combiner = args->call_combiner;
return GRPC_ERROR_NONE;
}
@@ -315,6 +345,7 @@ static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
const grpc_call_final_info *final_info,
grpc_closure *ignored) {
call_data *calld = elem->call_data;
+ grpc_credentials_mdelem_array_destroy(exec_ctx, &calld->md_array);
grpc_call_credentials_unref(exec_ctx, calld->creds);
if (calld->have_host) {
grpc_slice_unref_internal(exec_ctx, calld->host);
@@ -323,7 +354,6 @@ static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
grpc_slice_unref_internal(exec_ctx, calld->method);
}
reset_auth_metadata_context(&calld->auth_md_context);
- gpr_mu_destroy(&calld->security_context_mu);
}
/* Constructor for channel_data */
@@ -382,6 +412,5 @@ const grpc_channel_filter grpc_client_auth_filter = {
sizeof(channel_data),
init_channel_elem,
destroy_channel_elem,
- grpc_call_next_get_peer,
grpc_channel_next_get_info,
"client-auth"};
diff --git a/src/core/lib/security/transport/security_connector.c b/src/core/lib/security/transport/security_connector.c
index 6788126769..a7568b995f 100644
--- a/src/core/lib/security/transport/security_connector.c
+++ b/src/core/lib/security/transport/security_connector.c
@@ -136,15 +136,27 @@ void grpc_security_connector_check_peer(grpc_exec_ctx *exec_ctx,
}
}
-void grpc_channel_security_connector_check_call_host(
+bool grpc_channel_security_connector_check_call_host(
grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc,
const char *host, grpc_auth_context *auth_context,
- grpc_security_call_host_check_cb cb, void *user_data) {
+ grpc_closure *on_call_host_checked, grpc_error **error) {
if (sc == NULL || sc->check_call_host == NULL) {
- cb(exec_ctx, user_data, GRPC_SECURITY_ERROR);
- } else {
- sc->check_call_host(exec_ctx, sc, host, auth_context, cb, user_data);
+ *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+ "cannot check call host -- no security connector");
+ return true;
}
+ return sc->check_call_host(exec_ctx, sc, host, auth_context,
+ on_call_host_checked, error);
+}
+
+void grpc_channel_security_connector_cancel_check_call_host(
+ grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc,
+ grpc_closure *on_call_host_checked, grpc_error *error) {
+ if (sc == NULL || sc->cancel_check_call_host == NULL) {
+ GRPC_ERROR_UNREF(error);
+ return;
+ }
+ sc->cancel_check_call_host(exec_ctx, sc, on_call_host_checked, error);
}
#ifndef NDEBUG
@@ -368,13 +380,19 @@ static void fake_server_check_peer(grpc_exec_ctx *exec_ctx,
fake_check_peer(exec_ctx, sc, peer, auth_context, on_peer_checked);
}
-static void fake_channel_check_call_host(grpc_exec_ctx *exec_ctx,
+static bool fake_channel_check_call_host(grpc_exec_ctx *exec_ctx,
grpc_channel_security_connector *sc,
const char *host,
grpc_auth_context *auth_context,
- grpc_security_call_host_check_cb cb,
- void *user_data) {
- cb(exec_ctx, user_data, GRPC_SECURITY_OK);
+ grpc_closure *on_call_host_checked,
+ grpc_error **error) {
+ return true;
+}
+
+static void fake_channel_cancel_check_call_host(
+ grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc,
+ grpc_closure *on_call_host_checked, grpc_error *error) {
+ GRPC_ERROR_UNREF(error);
}
static void fake_channel_add_handshakers(
@@ -413,6 +431,7 @@ grpc_channel_security_connector *grpc_fake_channel_security_connector_create(
c->base.request_metadata_creds =
grpc_call_credentials_ref(request_metadata_creds);
c->base.check_call_host = fake_channel_check_call_host;
+ c->base.cancel_check_call_host = fake_channel_cancel_check_call_host;
c->base.add_handshakers = fake_channel_add_handshakers;
c->target = gpr_strdup(target);
const char *expected_targets = grpc_fake_transport_get_expected_targets(args);
@@ -663,26 +682,35 @@ void tsi_shallow_peer_destruct(tsi_peer *peer) {
if (peer->properties != NULL) gpr_free(peer->properties);
}
-static void ssl_channel_check_call_host(grpc_exec_ctx *exec_ctx,
+static bool ssl_channel_check_call_host(grpc_exec_ctx *exec_ctx,
grpc_channel_security_connector *sc,
const char *host,
grpc_auth_context *auth_context,
- grpc_security_call_host_check_cb cb,
- void *user_data) {
+ grpc_closure *on_call_host_checked,
+ grpc_error **error) {
grpc_ssl_channel_security_connector *c =
(grpc_ssl_channel_security_connector *)sc;
grpc_security_status status = GRPC_SECURITY_ERROR;
tsi_peer peer = tsi_shallow_peer_from_ssl_auth_context(auth_context);
if (ssl_host_matches_name(&peer, host)) status = GRPC_SECURITY_OK;
-
/* If the target name was overridden, then the original target_name was
'checked' transitively during the previous peer check at the end of the
handshake. */
if (c->overridden_target_name != NULL && strcmp(host, c->target_name) == 0) {
status = GRPC_SECURITY_OK;
}
- cb(exec_ctx, user_data, status);
+ if (status != GRPC_SECURITY_OK) {
+ *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+ "call host does not match SSL server name");
+ }
tsi_shallow_peer_destruct(&peer);
+ return true;
+}
+
+static void ssl_channel_cancel_check_call_host(
+ grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc,
+ grpc_closure *on_call_host_checked, grpc_error *error) {
+ GRPC_ERROR_UNREF(error);
}
static grpc_security_connector_vtable ssl_channel_vtable = {
@@ -811,6 +839,7 @@ grpc_security_status grpc_ssl_channel_security_connector_create(
c->base.request_metadata_creds =
grpc_call_credentials_ref(request_metadata_creds);
c->base.check_call_host = ssl_channel_check_call_host;
+ c->base.cancel_check_call_host = ssl_channel_cancel_check_call_host;
c->base.add_handshakers = ssl_channel_add_handshakers;
gpr_split_host_port(target_name, &c->target_name, &port);
gpr_free(port);
diff --git a/src/core/lib/security/transport/security_connector.h b/src/core/lib/security/transport/security_connector.h
index 1c0fe40045..4f9b63ad20 100644
--- a/src/core/lib/security/transport/security_connector.h
+++ b/src/core/lib/security/transport/security_connector.h
@@ -117,27 +117,38 @@ grpc_security_connector *grpc_security_connector_find_in_args(
typedef struct grpc_channel_security_connector grpc_channel_security_connector;
-typedef void (*grpc_security_call_host_check_cb)(grpc_exec_ctx *exec_ctx,
- void *user_data,
- grpc_security_status status);
-
struct grpc_channel_security_connector {
grpc_security_connector base;
grpc_call_credentials *request_metadata_creds;
- void (*check_call_host)(grpc_exec_ctx *exec_ctx,
+ bool (*check_call_host)(grpc_exec_ctx *exec_ctx,
grpc_channel_security_connector *sc, const char *host,
grpc_auth_context *auth_context,
- grpc_security_call_host_check_cb cb, void *user_data);
+ grpc_closure *on_call_host_checked,
+ grpc_error **error);
+ void (*cancel_check_call_host)(grpc_exec_ctx *exec_ctx,
+ grpc_channel_security_connector *sc,
+ grpc_closure *on_call_host_checked,
+ grpc_error *error);
void (*add_handshakers)(grpc_exec_ctx *exec_ctx,
grpc_channel_security_connector *sc,
grpc_handshake_manager *handshake_mgr);
};
-/* Checks that the host that will be set for a call is acceptable. */
-void grpc_channel_security_connector_check_call_host(
+/// Checks that the host that will be set for a call is acceptable.
+/// Returns true if completed synchronously, in which case \a error will
+/// be set to indicate the result. Otherwise, \a on_call_host_checked
+/// will be invoked when complete.
+bool grpc_channel_security_connector_check_call_host(
grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc,
const char *host, grpc_auth_context *auth_context,
- grpc_security_call_host_check_cb cb, void *user_data);
+ grpc_closure *on_call_host_checked, grpc_error **error);
+
+/// Cancels a pending asychronous call to
+/// grpc_channel_security_connector_check_call_host() with
+/// \a on_call_host_checked as its callback.
+void grpc_channel_security_connector_cancel_check_call_host(
+ grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc,
+ grpc_closure *on_call_host_checked, grpc_error *error);
/* Registers handshakers with \a handshake_mgr. */
void grpc_channel_security_connector_add_handshakers(
diff --git a/src/core/lib/security/transport/security_handshaker.c b/src/core/lib/security/transport/security_handshaker.c
index 239a211c0b..fc9c9f980f 100644
--- a/src/core/lib/security/transport/security_handshaker.c
+++ b/src/core/lib/security/transport/security_handshaker.c
@@ -147,7 +147,7 @@ static void on_peer_checked(grpc_exec_ctx *exec_ctx, void *arg,
goto done;
}
// Get unused bytes.
- unsigned char *unused_bytes = NULL;
+ const unsigned char *unused_bytes = NULL;
size_t unused_bytes_size = 0;
result = tsi_handshaker_result_get_unused_bytes(
h->handshaker_result, &unused_bytes, &unused_bytes_size);
@@ -261,7 +261,7 @@ static grpc_error *do_handshaker_next_locked(
grpc_exec_ctx *exec_ctx, security_handshaker *h,
const unsigned char *bytes_received, size_t bytes_received_size) {
// Invoke TSI handshaker.
- unsigned char *bytes_to_send = NULL;
+ const unsigned char *bytes_to_send = NULL;
size_t bytes_to_send_size = 0;
tsi_handshaker_result *handshaker_result = NULL;
tsi_result result = tsi_handshaker_next(
diff --git a/src/core/lib/security/transport/server_auth_filter.c b/src/core/lib/security/transport/server_auth_filter.c
index 9bf3f0ca0f..b721ce4a22 100644
--- a/src/core/lib/security/transport/server_auth_filter.c
+++ b/src/core/lib/security/transport/server_auth_filter.c
@@ -26,7 +26,15 @@
#include "src/core/lib/security/transport/auth_filters.h"
#include "src/core/lib/slice/slice_internal.h"
+typedef enum {
+ STATE_INIT = 0,
+ STATE_DONE,
+ STATE_CANCELLED,
+} async_state;
+
typedef struct call_data {
+ grpc_call_combiner *call_combiner;
+ grpc_call_stack *owning_call;
grpc_transport_stream_op_batch *recv_initial_metadata_batch;
grpc_closure *original_recv_initial_metadata_ready;
grpc_closure recv_initial_metadata_ready;
@@ -34,6 +42,8 @@ typedef struct call_data {
const grpc_metadata *consumed_md;
size_t num_consumed_md;
grpc_auth_context *auth_context;
+ grpc_closure cancel_closure;
+ gpr_atm state; // async_state
} call_data;
typedef struct channel_data {
@@ -78,54 +88,92 @@ static grpc_filtered_mdelem remove_consumed_md(grpc_exec_ctx *exec_ctx,
return GRPC_FILTERED_MDELEM(md);
}
-/* called from application code */
-static void on_md_processing_done(
- void *user_data, const grpc_metadata *consumed_md, size_t num_consumed_md,
- const grpc_metadata *response_md, size_t num_response_md,
- grpc_status_code status, const char *error_details) {
- grpc_call_element *elem = user_data;
+static void on_md_processing_done_inner(grpc_exec_ctx *exec_ctx,
+ grpc_call_element *elem,
+ const grpc_metadata *consumed_md,
+ size_t num_consumed_md,
+ const grpc_metadata *response_md,
+ size_t num_response_md,
+ grpc_error *error) {
call_data *calld = elem->call_data;
grpc_transport_stream_op_batch *batch = calld->recv_initial_metadata_batch;
- grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+ grpc_call_combiner_set_notify_on_cancel(exec_ctx, calld->call_combiner, NULL);
/* TODO(jboeuf): Implement support for response_md. */
if (response_md != NULL && num_response_md > 0) {
gpr_log(GPR_INFO,
"response_md in auth metadata processing not supported for now. "
"Ignoring...");
}
- grpc_error *error = GRPC_ERROR_NONE;
- if (status == GRPC_STATUS_OK) {
+ if (error == GRPC_ERROR_NONE) {
calld->consumed_md = consumed_md;
calld->num_consumed_md = num_consumed_md;
error = grpc_metadata_batch_filter(
- &exec_ctx, batch->payload->recv_initial_metadata.recv_initial_metadata,
+ exec_ctx, batch->payload->recv_initial_metadata.recv_initial_metadata,
remove_consumed_md, elem, "Response metadata filtering error");
- } else {
- if (error_details == NULL) {
- error_details = "Authentication metadata processing failed.";
+ }
+ GRPC_CLOSURE_SCHED(exec_ctx, calld->original_recv_initial_metadata_ready,
+ error);
+}
+
+// Called from application code.
+static void on_md_processing_done(
+ void *user_data, const grpc_metadata *consumed_md, size_t num_consumed_md,
+ const grpc_metadata *response_md, size_t num_response_md,
+ grpc_status_code status, const char *error_details) {
+ grpc_call_element *elem = user_data;
+ call_data *calld = elem->call_data;
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+ // If the call was not cancelled while we were in flight, process the result.
+ if (gpr_atm_full_cas(&calld->state, (gpr_atm)STATE_INIT,
+ (gpr_atm)STATE_DONE)) {
+ grpc_error *error = GRPC_ERROR_NONE;
+ if (status != GRPC_STATUS_OK) {
+ if (error_details == NULL) {
+ error_details = "Authentication metadata processing failed.";
+ }
+ error = grpc_error_set_int(
+ GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_details),
+ GRPC_ERROR_INT_GRPC_STATUS, status);
}
- error =
- grpc_error_set_int(GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_details),
- GRPC_ERROR_INT_GRPC_STATUS, status);
+ on_md_processing_done_inner(&exec_ctx, elem, consumed_md, num_consumed_md,
+ response_md, num_response_md, error);
}
+ // Clean up.
for (size_t i = 0; i < calld->md.count; i++) {
grpc_slice_unref_internal(&exec_ctx, calld->md.metadata[i].key);
grpc_slice_unref_internal(&exec_ctx, calld->md.metadata[i].value);
}
grpc_metadata_array_destroy(&calld->md);
- GRPC_CLOSURE_SCHED(&exec_ctx, calld->original_recv_initial_metadata_ready,
- error);
+ GRPC_CALL_STACK_UNREF(&exec_ctx, calld->owning_call, "server_auth_metadata");
grpc_exec_ctx_finish(&exec_ctx);
}
+static void cancel_call(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
+ grpc_call_element *elem = (grpc_call_element *)arg;
+ call_data *calld = elem->call_data;
+ // If the result was not already processed, invoke the callback now.
+ if (gpr_atm_full_cas(&calld->state, (gpr_atm)STATE_INIT,
+ (gpr_atm)STATE_CANCELLED)) {
+ on_md_processing_done_inner(exec_ctx, elem, NULL, 0, NULL, 0,
+ GRPC_ERROR_REF(error));
+ }
+}
+
static void recv_initial_metadata_ready(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error) {
- grpc_call_element *elem = arg;
+ grpc_call_element *elem = (grpc_call_element *)arg;
channel_data *chand = elem->channel_data;
call_data *calld = elem->call_data;
grpc_transport_stream_op_batch *batch = calld->recv_initial_metadata_batch;
if (error == GRPC_ERROR_NONE) {
if (chand->creds != NULL && chand->creds->processor.process != NULL) {
+ // We're calling out to the application, so we need to make sure
+ // to drop the call combiner early if we get cancelled.
+ GRPC_CLOSURE_INIT(&calld->cancel_closure, cancel_call, elem,
+ grpc_schedule_on_exec_ctx);
+ grpc_call_combiner_set_notify_on_cancel(exec_ctx, calld->call_combiner,
+ &calld->cancel_closure);
+ GRPC_CALL_STACK_REF(calld->owning_call, "server_auth_metadata");
calld->md = metadata_batch_to_md_array(
batch->payload->recv_initial_metadata.recv_initial_metadata);
chand->creds->processor.process(
@@ -159,6 +207,8 @@ static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
const grpc_call_element_args *args) {
call_data *calld = elem->call_data;
channel_data *chand = elem->channel_data;
+ calld->call_combiner = args->call_combiner;
+ calld->owning_call = args->call_stack;
GRPC_CLOSURE_INIT(&calld->recv_initial_metadata_ready,
recv_initial_metadata_ready, elem,
grpc_schedule_on_exec_ctx);
@@ -218,6 +268,5 @@ const grpc_channel_filter grpc_server_auth_filter = {
sizeof(channel_data),
init_channel_elem,
destroy_channel_elem,
- grpc_call_next_get_peer,
grpc_channel_next_get_info,
"server-auth"};