From 8cde3d7c20445289f7072f29029e44870beecc37 Mon Sep 17 00:00:00 2001
From: murgatroid99 <mlumish@google.com>
Date: Thu, 24 Sep 2015 16:11:19 -0700
Subject: [PATCH] Implemented credentials plugin interface

---
 src/node/ext/call.h         |  3 +++
 src/node/ext/credentials.cc | 34 ++++++++++++++++++++++++++++++++++
 src/node/ext/credentials.h  |  6 +++++-
 3 files changed, 42 insertions(+), 1 deletion(-)

diff --git a/src/node/ext/call.h b/src/node/ext/call.h
index 2f8e1f17aa..d965f339fc 100644
--- a/src/node/ext/call.h
+++ b/src/node/ext/call.h
@@ -66,6 +66,9 @@ inline v8::Local<v8::Value> nanErrorWithCode(const char *msg,
     return scope.Escape(err);
 }
 
+bool CreateMetadataArray(Local<Object> metadata, grpc_metadata_array *array,
+                         shared_ptr<Resources> resources);
+
 v8::Local<v8::Value> ParseMetadata(const grpc_metadata_array *metadata_array);
 
 struct Resources {
diff --git a/src/node/ext/credentials.cc b/src/node/ext/credentials.cc
index 378031a4c1..3460365056 100644
--- a/src/node/ext/credentials.cc
+++ b/src/node/ext/credentials.cc
@@ -37,6 +37,7 @@
 #include "grpc/grpc_security.h"
 #include "grpc/support/log.h"
 #include "credentials.h"
+#include "call.h"
 
 namespace grpc {
 namespace node {
@@ -262,6 +263,39 @@ NAN_METHOD(Credentials::CreateFromPlugin) {
   }
 }
 
+NAN_METHOD(PluginCallback) {
+  // Arguments: status code, error details, metadata
+  if (!info[0]->IsUint32()) {
+    return Nan::ThrowTypeError(
+        "The callback's first argument must be a status code");
+  }
+  if (!info[1]->IsString()) {
+    return Nan::ThrowTypeError(
+        "The callback's second argument must be a string");
+  }
+  if (!info[2]->IsObject()) {
+    return Nan::ThrowTypeError(
+        "The callback's third argument must be an object");
+  }
+  grpc_status_code code = static_cast<grpc_status_code>(
+      Nan::To<uint32_t>(info[0]).FromJust());
+  char *details = *Nan::Utf8String(info[1]);
+  grpc_metadata_array array;
+  if (!CreateMetadataArray(Nan::To<Object>(info[2]).ToLocalChecked(),
+                           &array, shared_ptr<Resources>(new Resources))){
+    return Nan::ThrowError("Failed to parse metadata");
+  }
+  grpc_credentials_plugin_metadata_cb cb =
+      reinterpret_cast<grpc_credentials_plugin_metadata_cb>(
+          Nan::To<External>(
+              Nan::Get(info.Callee, "cb").ToLocalChecked()
+                            ).ToLocalChecked()->Value());
+  void *user_data = Nan::To<External>(
+      Nan::Get(info.Callee, "user_data").ToLocalChecked()
+                                      ).ToLocalChecked()->Value();
+  cb(user_data, array.metadata, array.count, code, details);
+}
+
 void plugin_get_metadata(void *state, const char *service_url,
                          grpc_credentials_plugin_metadata_cb cb,
                          void *user_data) {
diff --git a/src/node/ext/credentials.h b/src/node/ext/credentials.h
index 553ef81c19..94ed884228 100644
--- a/src/node/ext/credentials.h
+++ b/src/node/ext/credentials.h
@@ -102,9 +102,13 @@ NAN_INLINE NAUV_WORK_CB(SendPluginCallback) {
   Nan::HandleScope scope;
   plugin_callback_data *data = reinterpret_cast<plugin_callback_data>(
       async->data);
+  // Attach cb and user_data to plugin_callback so that it can access them later
   v8::Local<v8::Function> plugin_callback = Nan::GetFunction(
       Nan::New<v8::FunctionTemplate>(PluginCallback).ToLocalChecked());
-  // Attach cb and user_data to plugin_callback so that it can access them later
+  Nan::Set(plugin_callback, Nan::New("cb").ToLocalChecked(),
+           Nan::New<v8::External>(reinterpret_cast<void*>(data->cb)));
+  Nan::Set(plugin_callback, Nan::New("user_data").ToLocalChecked(),
+           Nan::New<v8::External>(data->user_data));
   const int argc = 2;
   v8::Local<v8::Value> argv = {Nan::New(data->service_url).ToLocalChecked(),
                                plugin_callback};
-- 
GitLab