+ for (idx = 0; plugin->apis[idx].callback != NULL; idx++) {
+ if (!strcmp(plugin->apis[idx].name, request->api)) {
+
+ // Request was found and at least partially executed
+ request->jresp = json_object_new_object();
+ json_object_get (afbJsonType); // increate jsontype reference count
+ json_object_object_add (request->jresp, "jtype", afbJsonType);
+
+ // prepare an object to store calling values
+ jcall=json_object_new_object();
+ json_object_object_add(jcall, "prefix", json_object_new_string (plugin->prefix));
+ json_object_object_add(jcall, "api" , json_object_new_string (plugin->apis[idx].name));
+
+ // save context before calling the API
+ status = setjmp (request->checkPluginCall);
+ if (status != 0) {
+
+ // Plugin aborted somewhere during its execution
+ json_object_object_add(jcall, "status", json_object_new_string ("abort"));
+ json_object_object_add(jcall, "info" , json_object_new_string ("Plugin broke during execution"));
+ json_object_object_add(request->jresp, "request", jcall);
+
+ } else {
+
+ // If timeout protection==0 we are in debug and we do not apply signal protection
+ if (request->config->apiTimeout > 0) {
+ for (sig=0; signals[sig] != 0; sig++) {
+ if (signal (signals[sig], pluginError) == SIG_ERR) {
+ request->errcode = MHD_HTTP_UNPROCESSABLE_ENTITY;
+ json_object_object_add(jcall, "status", json_object_new_string ("fail"));
+ json_object_object_add(jcall, "info", json_object_new_string ("Setting Timeout Handler Failed"));
+ json_object_object_add(request->jresp, "request", jcall);
+ return AFB_DONE;
+ }
+ }
+ // Trigger a timer to protect from unacceptable long time execution
+ alarm (request->config->apiTimeout);
+ }
+
+ // Out of SessionNone every call get a client context session
+ if (AFB_SESSION_NONE != plugin->apis[idx].session) {
+
+ // add client context to request
+ ctxClientGet(request, plugin);
+
+ if (verbose) fprintf(stderr, "Plugin=[%s] Api=[%s] Middleware=[%d] Client=[0x%x] Uuid=[%s] Token=[%s]\n"
+ , request->plugin, request->api, plugin->apis[idx].session, request->client, request->client->uuid, request->client->token);
+
+ switch(plugin->apis[idx].session) {
+
+ case AFB_SESSION_CREATE:
+ if (request->client->token[0] != '\0') {
+ request->errcode=MHD_HTTP_UNAUTHORIZED;
+ json_object_object_add(jcall, "status", json_object_new_string ("exist"));
+ json_object_object_add(jcall, "info", json_object_new_string ("AFB_SESSION_CREATE Session already exist"));
+ json_object_object_add(request->jresp, "request", jcall);
+ return (AFB_DONE);
+ }
+
+ if (AFB_SUCCESS != ctxTokenCreate (request)) {
+ request->errcode=MHD_HTTP_UNAUTHORIZED;
+ json_object_object_add(jcall, "status", json_object_new_string ("fail"));
+ json_object_object_add(jcall, "info", json_object_new_string ("AFB_SESSION_CREATE Invalid Initial Token"));
+ json_object_object_add(request->jresp, "request", jcall);
+ return (AFB_DONE);
+ } else {
+ json_object_object_add(jcall, "uuid", json_object_new_string (request->client->uuid));
+ json_object_object_add(jcall, "token", json_object_new_string (request->client->token));
+ }
+ break;
+
+
+ case AFB_SESSION_RENEW:
+ if (AFB_SUCCESS != ctxTokenRefresh (request)) {
+ request->errcode=MHD_HTTP_UNAUTHORIZED;
+ json_object_object_add(jcall, "status", json_object_new_string ("fail"));
+ json_object_object_add(jcall, "info", json_object_new_string ("AFB_SESSION_REFRESH Broken Exchange Token Chain"));
+ json_object_object_add(request->jresp, "request", jcall);
+ return (AFB_DONE);
+ } else {
+ json_object_object_add(jcall, "uuid", json_object_new_string (request->client->uuid));
+ json_object_object_add(jcall, "token", json_object_new_string (request->client->token));
+ }
+ break;
+
+ case AFB_SESSION_CLOSE:
+ if (AFB_SUCCESS != ctxTokenCheck (request)) {
+ request->errcode=MHD_HTTP_UNAUTHORIZED;
+ json_object_object_add(jcall, "status", json_object_new_string ("empty"));
+ json_object_object_add(jcall, "info", json_object_new_string ("AFB_SESSION_CLOSE Not a Valid Access Token"));
+ json_object_object_add(request->jresp, "request", jcall);
+ return (AFB_DONE);
+ } else {
+ json_object_object_add(jcall, "uuid", json_object_new_string (request->client->uuid));
+ }
+ break;
+
+ case AFB_SESSION_CHECK:
+ default:
+ // default action is check
+ if (AFB_SUCCESS != ctxTokenCheck (request)) {
+ request->errcode=MHD_HTTP_UNAUTHORIZED;
+ json_object_object_add(jcall, "status", json_object_new_string ("fail"));
+ json_object_object_add(jcall, "info", json_object_new_string ("AFB_SESSION_CHECK Invalid Active Token"));
+ json_object_object_add(request->jresp, "request", jcall);
+ return (AFB_DONE);
+ }
+ break;
+ }
+ }
+
+ // Effectively call the API with a subset of the context
+ jresp = plugin->apis[idx].callback(request, context);
+
+ // Session close is done after the API call so API can still use session in closing API
+ if (AFB_SESSION_CLOSE == plugin->apis[idx].session) ctxTokenReset (request);
+
+ // API should return NULL of a valid Json Object
+ if (jresp == NULL) {
+ json_object_object_add(jcall, "status", json_object_new_string ("null"));
+ json_object_object_add(request->jresp, "request", jcall);
+ request->errcode = MHD_HTTP_NO_RESPONSE;
+
+ } else {
+ json_object_object_add(jcall, "status", json_object_new_string ("processed"));
+ json_object_object_add(request->jresp, "request", jcall);
+ json_object_object_add(request->jresp, "response", jresp);
+ }
+ // cancel timeout and plugin signal handle before next call
+ if (request->config->apiTimeout > 0) {
+ alarm (0);
+ for (sig=0; signals[sig] != 0; sig++) {
+ signal (signals[sig], SIG_DFL);
+ }
+ }
+ }
+ return (AFB_DONE);
+ }