work in progress (tbf)
[src/app-framework-binder.git] / src / afb-apis.c
index ca42743..8fbd9fc 100644 (file)
 #include <limits.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <signal.h>
+#include <time.h>
+#include <sys/syscall.h>
+#include <setjmp.h>
 
-#include "../include/local-def.h"
+#include "local-def.h"
 
 #include "afb-req-itf.h"
 #include "afb-apis.h"
@@ -45,6 +49,7 @@ struct api_desc {
        void *handle;           /* context of dlopen */
 };
 
+static int api_timeout = 15;
 static struct api_desc *apis_array = NULL;
 static int apis_count = 0;
 
@@ -279,33 +284,48 @@ int afb_apis_add_pathset(const char *pathset)
        };
 }
 
-/*
 // Check of apiurl is declare in this plugin and call it
 extern __thread sigjmp_buf *error_handler;
-static int callPluginApi(AFB_request * request)
+static void trapping_handle(AFB_request * request, struct json_object *(*cb)(AFB_request *,void*))
 {
+       volatile int signum, timerset;
+       timer_t timerid;
        sigjmp_buf jmpbuf, *older;
+       struct sigevent sevp;
+       struct itimerspec its;
 
        // save context before calling the API
-       status = setjmp(jmpbuf);
-       if (status != 0) {
-               return 0;
+       timerset = 0;
+       older = error_handler;
+       signum = setjmp(jmpbuf);
+       if (signum != 0) {
+               afb_req_fail_f(*request->areq, "aborted", "signal %d caught", signum);
        }
+       else {
+               error_handler = &jmpbuf;
+               if (api_timeout > 0) {
+                       timerset = 1; /* TODO: check statuses */
+                       sevp.sigev_notify = SIGEV_THREAD_ID;
+                       sevp.sigev_signo = SIGALRM;
+#if defined(sigev_notify_thread_id)
+                       sevp.sigev_notify_thread_id = (pid_t)syscall(SYS_gettid);
+#else
+                       sevp._sigev_un._tid = (pid_t)syscall(SYS_gettid);
+#endif
+                       timer_create(CLOCK_THREAD_CPUTIME_ID, &sevp, &timerid);
+                       its.it_interval.tv_sec = 0;
+                       its.it_interval.tv_nsec = 0;
+                       its.it_value.tv_sec = api_timeout;
+                       its.it_value.tv_nsec = 0;
+                       timer_settime(timerid, 0, &its, NULL);
+               }
 
-       // Trigger a timer to protect from unacceptable long time execution
-       if (request->config->apiTimeout > 0)
-               alarm((unsigned)request->config->apiTimeout);
-
-       older = error_handler;
-       error_handler = &jmpbuf;
-       doCallPluginApi(request, apiidx, verbidx, context);
+               cb(request, NULL);
+       }
+       if (timerset)
+               timer_delete(timerid);
        error_handler = older;
-
-       // cancel timeout and plugin signal handle before next call
-       alarm(0);
-       return 1;
 }
-*/
 
 static void handle(struct afb_req req, const struct api_desc *api, const struct AFB_restapi *verb)
 {
@@ -333,10 +353,10 @@ static void handle(struct afb_req req, const struct api_desc *api, const struct
        default:
                break;
        }
-       verb->callback(&request, NULL);
+       trapping_handle(&request, verb->callback);
 
        if (verb->session == AFB_SESSION_CLOSE)
-               /*del*/;
+               /*close*/;
 }
 
 int afb_apis_handle(struct afb_req req, const char *api, size_t lenapi, const char *verb, size_t lenverb)
@@ -347,7 +367,7 @@ int afb_apis_handle(struct afb_req req, const char *api, size_t lenapi, const ch
 
        a = apis_array;
        for (i = 0 ; i < apis_count ; i++, a++) {
-               if (a->prefixlen == lenapi && !strcasecmp(a->prefix, api)) {
+               if (a->prefixlen == lenapi && !strncasecmp(a->prefix, api, lenapi)) {
                        v = a->plugin->apis;
                        for (j = 0 ; v->name ; j++, v++) {
                                if (!strncasecmp(v->name, verb, lenverb) && !v->name[lenverb]) {
@@ -355,7 +375,8 @@ int afb_apis_handle(struct afb_req req, const char *api, size_t lenapi, const ch
                                        return 1;
                                }
                        }
-                       break;
+                       afb_req_fail_f(req, "unknown-verb", "verb %.*s unknown within api %s", (int)lenverb, verb, a->prefix);
+                       return 1;
                }
        }
        return 0;