aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/lib/security/transport/server_auth_filter.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/lib/security/transport/server_auth_filter.cc')
-rw-r--r--src/core/lib/security/transport/server_auth_filter.cc115
1 files changed, 86 insertions, 29 deletions
diff --git a/src/core/lib/security/transport/server_auth_filter.cc b/src/core/lib/security/transport/server_auth_filter.cc
index 19cbb03b63..362f49a584 100644
--- a/src/core/lib/security/transport/server_auth_filter.cc
+++ b/src/core/lib/security/transport/server_auth_filter.cc
@@ -28,6 +28,9 @@
#include "src/core/lib/security/transport/auth_filters.h"
#include "src/core/lib/slice/slice_internal.h"
+static void recv_initial_metadata_ready(void* arg, grpc_error* error);
+static void recv_trailing_metadata_ready(void* user_data, grpc_error* error);
+
namespace {
enum async_state {
STATE_INIT = 0,
@@ -35,23 +38,55 @@ enum async_state {
STATE_CANCELLED,
};
+struct channel_data {
+ grpc_auth_context* auth_context;
+ grpc_server_credentials* creds;
+};
+
struct call_data {
+ call_data(grpc_call_element* elem, const grpc_call_element_args& args)
+ : call_combiner(args.call_combiner), owning_call(args.call_stack) {
+ GRPC_CLOSURE_INIT(&recv_initial_metadata_ready,
+ ::recv_initial_metadata_ready, elem,
+ grpc_schedule_on_exec_ctx);
+ GRPC_CLOSURE_INIT(&recv_trailing_metadata_ready,
+ ::recv_trailing_metadata_ready, elem,
+ grpc_schedule_on_exec_ctx);
+ // Create server security context. Set its auth context from channel
+ // data and save it in the call context.
+ grpc_server_security_context* server_ctx =
+ grpc_server_security_context_create(args.arena);
+ channel_data* chand = static_cast<channel_data*>(elem->channel_data);
+ server_ctx->auth_context =
+ GRPC_AUTH_CONTEXT_REF(chand->auth_context, "server_auth_filter");
+ if (args.context[GRPC_CONTEXT_SECURITY].value != nullptr) {
+ args.context[GRPC_CONTEXT_SECURITY].destroy(
+ args.context[GRPC_CONTEXT_SECURITY].value);
+ }
+ args.context[GRPC_CONTEXT_SECURITY].value = server_ctx;
+ args.context[GRPC_CONTEXT_SECURITY].destroy =
+ grpc_server_security_context_destroy;
+ }
+
+ ~call_data() { GRPC_ERROR_UNREF(recv_initial_metadata_error); }
+
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;
+ grpc_error* recv_initial_metadata_error = GRPC_ERROR_NONE;
+ grpc_closure recv_trailing_metadata_ready;
+ grpc_closure* original_recv_trailing_metadata_ready;
+ grpc_error* recv_trailing_metadata_error;
+ bool seen_recv_trailing_metadata_ready = false;
grpc_metadata_array md;
const grpc_metadata* consumed_md;
size_t num_consumed_md;
grpc_closure cancel_closure;
- gpr_atm state; // async_state
+ gpr_atm state = STATE_INIT; // async_state
};
-struct channel_data {
- grpc_auth_context* auth_context;
- grpc_server_credentials* creds;
-};
} // namespace
static grpc_metadata_array metadata_batch_to_md_array(
@@ -111,7 +146,16 @@ static void on_md_processing_done_inner(grpc_call_element* elem,
batch->payload->recv_initial_metadata.recv_initial_metadata,
remove_consumed_md, elem, "Response metadata filtering error");
}
- GRPC_CLOSURE_SCHED(calld->original_recv_initial_metadata_ready, error);
+ calld->recv_initial_metadata_error = GRPC_ERROR_REF(error);
+ grpc_closure* closure = calld->original_recv_initial_metadata_ready;
+ calld->original_recv_initial_metadata_ready = nullptr;
+ if (calld->seen_recv_trailing_metadata_ready) {
+ GRPC_CALL_COMBINER_START(calld->call_combiner,
+ &calld->recv_trailing_metadata_ready,
+ calld->recv_trailing_metadata_error,
+ "continue recv_trailing_metadata_ready");
+ }
+ GRPC_CLOSURE_SCHED(closure, error);
}
// Called from application code.
@@ -180,8 +224,31 @@ static void recv_initial_metadata_ready(void* arg, grpc_error* error) {
return;
}
}
- GRPC_CLOSURE_RUN(calld->original_recv_initial_metadata_ready,
- GRPC_ERROR_REF(error));
+ grpc_closure* closure = calld->original_recv_initial_metadata_ready;
+ calld->original_recv_initial_metadata_ready = nullptr;
+ if (calld->seen_recv_trailing_metadata_ready) {
+ GRPC_CALL_COMBINER_START(calld->call_combiner,
+ &calld->recv_trailing_metadata_ready,
+ calld->recv_trailing_metadata_error,
+ "continue recv_trailing_metadata_ready");
+ }
+ GRPC_CLOSURE_RUN(closure, GRPC_ERROR_REF(error));
+}
+
+static void recv_trailing_metadata_ready(void* user_data, grpc_error* err) {
+ grpc_call_element* elem = static_cast<grpc_call_element*>(user_data);
+ call_data* calld = static_cast<call_data*>(elem->call_data);
+ if (calld->original_recv_initial_metadata_ready != nullptr) {
+ calld->recv_trailing_metadata_error = GRPC_ERROR_REF(err);
+ calld->seen_recv_trailing_metadata_ready = true;
+ GRPC_CALL_COMBINER_STOP(calld->call_combiner,
+ "deferring recv_trailing_metadata_ready until "
+ "after recv_initial_metadata_ready");
+ return;
+ }
+ err = grpc_error_add_child(
+ GRPC_ERROR_REF(err), GRPC_ERROR_REF(calld->recv_initial_metadata_error));
+ GRPC_CLOSURE_RUN(calld->original_recv_trailing_metadata_ready, err);
}
static void auth_start_transport_stream_op_batch(
@@ -195,39 +262,29 @@ static void auth_start_transport_stream_op_batch(
batch->payload->recv_initial_metadata.recv_initial_metadata_ready =
&calld->recv_initial_metadata_ready;
}
+ if (batch->recv_trailing_metadata) {
+ calld->original_recv_trailing_metadata_ready =
+ batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready;
+ batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready =
+ &calld->recv_trailing_metadata_ready;
+ }
grpc_call_next_op(elem, batch);
}
/* Constructor for call_data */
static grpc_error* init_call_elem(grpc_call_element* elem,
const grpc_call_element_args* args) {
- call_data* calld = static_cast<call_data*>(elem->call_data);
- channel_data* chand = static_cast<channel_data*>(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);
- // Create server security context. Set its auth context from channel
- // data and save it in the call context.
- grpc_server_security_context* server_ctx =
- grpc_server_security_context_create(args->arena);
- server_ctx->auth_context =
- GRPC_AUTH_CONTEXT_REF(chand->auth_context, "server_auth_filter");
- if (args->context[GRPC_CONTEXT_SECURITY].value != nullptr) {
- args->context[GRPC_CONTEXT_SECURITY].destroy(
- args->context[GRPC_CONTEXT_SECURITY].value);
- }
- args->context[GRPC_CONTEXT_SECURITY].value = server_ctx;
- args->context[GRPC_CONTEXT_SECURITY].destroy =
- grpc_server_security_context_destroy;
+ new (elem->call_data) call_data(elem, *args);
return GRPC_ERROR_NONE;
}
/* Destructor for call_data */
static void destroy_call_elem(grpc_call_element* elem,
const grpc_call_final_info* final_info,
- grpc_closure* ignored) {}
+ grpc_closure* ignored) {
+ call_data* calld = static_cast<call_data*>(elem->call_data);
+ calld->~call_data();
+}
/* Constructor for channel_data */
static grpc_error* init_channel_elem(grpc_channel_element* elem,