Few improvements:

- Guarantee the lifetime of objects passed to the processor.
- Add an option for implementers of the processor to make it
  non-blocking.
pull/2933/head
Julien Boeuf 9 years ago
parent d3920a28c6
commit bf25bb01bb
  1. 4
      include/grpc++/auth_metadata_processor.h
  2. 5
      include/grpc/grpc_security.h
  3. 8
      src/core/security/server_auth_filter.c
  4. 37
      src/cpp/server/secure_server_credentials.cc
  5. 5
      src/cpp/server/secure_server_credentials.h

@ -45,6 +45,10 @@ class AuthMetadataProcessor {
public: public:
virtual ~AuthMetadataProcessor() {} virtual ~AuthMetadataProcessor() {}
// If this method returns true, the Process function will be scheduled in
// a different thread as the one processing the call.
virtual bool IsBlocking() const { return true; }
// context is read/write: it contains the properties of the channel peer and // context is read/write: it contains the properties of the channel peer and
// it is the job of the Process method to augment it with properties derived // it is the job of the Process method to augment it with properties derived
// from the passed-in auth_metadata. // from the passed-in auth_metadata.

@ -286,9 +286,10 @@ typedef void (*grpc_process_auth_metadata_done_cb)(
typedef struct { typedef struct {
/* The context object is read/write: it contains the properties of the /* The context object is read/write: it contains the properties of the
channel peer and it is the job of the process function to augment it with channel peer and it is the job of the process function to augment it with
properties derived from the passed-in metadata. */ properties derived from the passed-in metadata.
The lifetime of these objects is guaranteed until cb is invoked. */
void (*process)(void *state, grpc_auth_context *context, void (*process)(void *state, grpc_auth_context *context,
const grpc_metadata *md, size_t md_count, const grpc_metadata *md, size_t num_md,
grpc_process_auth_metadata_done_cb cb, void *user_data); grpc_process_auth_metadata_done_cb cb, void *user_data);
void *state; void *state;
} grpc_auth_metadata_processor; } grpc_auth_metadata_processor;

@ -50,6 +50,7 @@ typedef struct call_data {
handling it. */ handling it. */
grpc_iomgr_closure auth_on_recv; grpc_iomgr_closure auth_on_recv;
grpc_transport_stream_op transport_op; grpc_transport_stream_op transport_op;
grpc_metadata_array md;
const grpc_metadata *consumed_md; const grpc_metadata *consumed_md;
size_t num_consumed_md; size_t num_consumed_md;
grpc_stream_op *md_op; grpc_stream_op *md_op;
@ -124,6 +125,7 @@ static void on_md_processing_done(void *user_data,
GRPC_STATUS_UNAUTHENTICATED, &message); GRPC_STATUS_UNAUTHENTICATED, &message);
grpc_call_next_op(elem, &calld->transport_op); grpc_call_next_op(elem, &calld->transport_op);
} }
grpc_metadata_array_destroy(&calld->md);
} }
static void auth_on_recv(void *user_data, int success) { static void auth_on_recv(void *user_data, int success) {
@ -135,17 +137,15 @@ static void auth_on_recv(void *user_data, int success) {
size_t nops = calld->recv_ops->nops; size_t nops = calld->recv_ops->nops;
grpc_stream_op *ops = calld->recv_ops->ops; grpc_stream_op *ops = calld->recv_ops->ops;
for (i = 0; i < nops; i++) { for (i = 0; i < nops; i++) {
grpc_metadata_array md_array;
grpc_stream_op *op = &ops[i]; grpc_stream_op *op = &ops[i];
if (op->type != GRPC_OP_METADATA || calld->got_client_metadata) continue; if (op->type != GRPC_OP_METADATA || calld->got_client_metadata) continue;
calld->got_client_metadata = 1; calld->got_client_metadata = 1;
if (chand->processor.process == NULL) continue; if (chand->processor.process == NULL) continue;
calld->md_op = op; calld->md_op = op;
md_array = metadata_batch_to_md_array(&op->data.metadata); calld->md = metadata_batch_to_md_array(&op->data.metadata);
chand->processor.process(chand->processor.state, calld->auth_context, chand->processor.process(chand->processor.state, calld->auth_context,
md_array.metadata, md_array.count, calld->md.metadata, calld->md.count,
on_md_processing_done, elem); on_md_processing_done, elem);
grpc_metadata_array_destroy(&md_array);
return; return;
} }
} }

@ -44,27 +44,36 @@
namespace grpc { namespace grpc {
void AuthMetadataProcessorAyncWrapper::Process( void AuthMetadataProcessorAyncWrapper::Process(
void* self, grpc_auth_context* context, const grpc_metadata* md, void* wrapper, grpc_auth_context* context, const grpc_metadata* md,
size_t md_count, grpc_process_auth_metadata_done_cb cb, void* user_data) { size_t num_md, grpc_process_auth_metadata_done_cb cb, void* user_data) {
auto* instance = reinterpret_cast<AuthMetadataProcessorAyncWrapper*>(self); auto* w = reinterpret_cast<AuthMetadataProcessorAyncWrapper*>(wrapper);
auto* metadata(new Metadata); if (w->processor_ == nullptr) {
for (size_t i = 0; i < md_count; i++) { // Early exit.
metadata->insert(std::make_pair( cb(user_data, NULL, 0, 1);
md[i].key, grpc::string(md[i].value, md[i].value_length))); return;
}
if (w->processor_->IsBlocking()) {
w->thread_pool_->Add(
std::bind(&AuthMetadataProcessorAyncWrapper::InvokeProcessor, w,
context, md, num_md, cb, user_data));
} else {
// invoke directly.
w->InvokeProcessor(context, md, num_md, cb, user_data);
} }
instance->thread_pool_->Add(
std::bind(&AuthMetadataProcessorAyncWrapper::ProcessAsync, instance,
context, metadata, cb, user_data));
} }
void AuthMetadataProcessorAyncWrapper::ProcessAsync( void AuthMetadataProcessorAyncWrapper::InvokeProcessor(
grpc_auth_context* ctx, grpc_auth_context* ctx,
Metadata* metadata, const grpc_metadata* md, size_t num_md,
grpc_process_auth_metadata_done_cb cb, void* user_data) { grpc_process_auth_metadata_done_cb cb, void* user_data) {
std::unique_ptr<Metadata> metadata_deleter(metadata); Metadata metadata;
for (size_t i = 0; i < num_md; i++) {
metadata.insert(std::make_pair(
md[i].key, grpc::string(md[i].value, md[i].value_length)));
}
SecureAuthContext context(ctx); SecureAuthContext context(ctx);
Metadata consumed_metadata; Metadata consumed_metadata;
bool ok = processor_->Process(*metadata, &context, &consumed_metadata); bool ok = processor_->Process(metadata, &context, &consumed_metadata);
if (ok) { if (ok) {
std::vector<grpc_metadata> consumed_md(consumed_metadata.size()); std::vector<grpc_metadata> consumed_md(consumed_metadata.size());
for (const auto& entry : consumed_metadata) { for (const auto& entry : consumed_metadata) {

@ -55,8 +55,9 @@ class AuthMetadataProcessorAyncWrapper GRPC_FINAL {
private: private:
typedef std::multimap<grpc::string, grpc::string> Metadata; typedef std::multimap<grpc::string, grpc::string> Metadata;
void ProcessAsync(grpc_auth_context* context, Metadata* auth_metadata, void InvokeProcessor(grpc_auth_context* context, const grpc_metadata* md,
grpc_process_auth_metadata_done_cb cb, void* user_data); size_t md_count, grpc_process_auth_metadata_done_cb cb,
void* user_data);
std::unique_ptr<ThreadPoolInterface> thread_pool_; std::unique_ptr<ThreadPoolInterface> thread_pool_;
std::shared_ptr<AuthMetadataProcessor> processor_; std::shared_ptr<AuthMetadataProcessor> processor_;
}; };

Loading…
Cancel
Save