work in progress, session handling
authorJosé Bollo <jose.bollo@iot.bzh>
Mon, 4 Apr 2016 15:48:50 +0000 (17:48 +0200)
committerJosé Bollo <jose.bollo@iot.bzh>
Mon, 4 Apr 2016 15:48:50 +0000 (17:48 +0200)
Change-Id: I0393346280825e24a34e8db386160d857723b841
Signed-off-by: José Bollo <jose.bollo@iot.bzh>
16 files changed:
include/afb-plugin.h
include/afb-req-itf.h
plugins/CMakeLists.txt
plugins/afm-main-plugin/afm-main-plugin.c
plugins/samples/ClientCtx.c
plugins/samples/HelloWorld.c
plugins/session/token-api.c
src/afb-apis.c
src/afb-apis.h
src/afb-hreq.c
src/afb-hreq.h
src/http-svc.c
src/local-def.h
src/main.c
src/session.c
src/session.h

index 8ca7270..f2f4d6e 100644 (file)
@@ -54,12 +54,27 @@ struct AFB_plugin
        void (*freeCtxCB)(void*);  // callback to free application context [null for standard free]
 };
 
+/* config mode */
+enum AFB_Mode {
+       AFB_MODE_LOCAL = 0,
+       AFB_MODE_REMOTE,
+       AFB_MODE_GLOBAL
+};
+
+/*
 typedef enum AFB_pluginE AFB_pluginE;
 typedef enum AFB_sessionE AFB_sessionE;
 typedef void (*AFB_apiCB)(struct afb_req);
 typedef void (*AFB_freeCtxCB)(void*);
 typedef struct AFB_restapi AFB_restapi;
 typedef struct AFB_plugin AFB_plugin;
+*/
+
+struct AFB_interface
+{
+       int verbose;
+       enum AFB_Mode mode;
+};
 
-extern const struct AFB_plugin *pluginRegister ();
+extern const struct AFB_plugin *pluginRegister (const struct AFB_interface *interface);
 
index c593440..a9b768d 100644 (file)
@@ -29,12 +29,15 @@ struct afb_req_itf {
        void (*iterate)(void *data, int (*iterator)(void *closure, struct afb_arg arg), void *closure);
        void (*fail)(void *data, const char *status, const char *info);
        void (*success)(void *data, struct json_object *obj, const char *info);
+       int (*session_create)(void *data);
+       int (*session_check)(void *data, int refresh);
+       void (*session_close)(void *data);
 };
 
 struct afb_req {
        const struct afb_req_itf *itf;
        void *data;
-       void **context;
+       void *context;
 };
 
 static inline struct afb_arg afb_req_get(struct afb_req req, const char *name)
@@ -67,6 +70,27 @@ static inline void afb_req_success(struct afb_req req, struct json_object *obj,
        req.itf->success(req.data, obj, info);
 }
 
+static inline int afb_req_session_create(struct afb_req req)
+{
+       int result = req.itf->session_create(req.data);
+       if (!result)
+               afb_req_fail(req, "fail", "Can't create the session");
+       return result;
+}
+
+static inline int afb_req_session_check(struct afb_req req, int refresh)
+{
+       int result = req.itf->session_check(req.data, refresh);
+       if (!result)
+               afb_req_fail(req, "fail", "Token chek failed for the session");
+       return result;
+}
+
+static inline void afb_req_session_close(struct afb_req req)
+{
+       req.itf->session_close(req.data);
+}
+
 #if !defined(_GNU_SOURCE)
 # error "_GNU_SOURCE must be defined for using vasprintf"
 #endif
index 5d8b26a..c60e352 100644 (file)
@@ -1,4 +1,4 @@
-#ADD_SUBDIRECTORY(afm-main-plugin)
+ADD_SUBDIRECTORY(afm-main-plugin)
 ADD_SUBDIRECTORY(session)
 ADD_SUBDIRECTORY(samples)
 #ADD_SUBDIRECTORY(audio)
index 0b6b868..fbf5b59 100644 (file)
 
 #define _GNU_SOURCE         /* See feature_test_macros(7) */
 #include <stdio.h>
+#include <string.h>
+#include <json.h>
 
-#include "local-def.h"
+#include "afb-plugin.h"
+#include "afb-req-itf.h"
 
 #include "utils-jbus.h"
 
-static const char _id_[]    = "id";
-static const char _runid_[] = "runid";
-static char _runnables_[]   = "runnables";
-static char _detail_[]      = "detail";
-static char _start_[]       = "start";
-static char _terminate_[]   = "terminate";
-static char _stop_[]        = "stop";
-static char _continue_[]    = "continue";
-static char _runners_[]     = "runners";
-static char _state_[]       = "state";
-static char _install_[]     = "install";
-static char _uninstall_[]   = "uninstall";
-static const char _mode_[]  = "mode";
-static const char _local_[] = "local";
-static const char _remote_[]= "remote";
-static const char _auto_[]  = "auto";
-static const char _uri_[]   = "uri";
+static const char _auto_[]      = "auto";
+static const char _continue_[]  = "continue";
+static const char _detail_[]    = "detail";
+static const char _id_[]        = "id";
+static const char _install_[]   = "install";
+static const char _local_[]     = "local";
+static const char _mode_[]      = "mode";
+static const char _remote_[]    = "remote";
+static const char _runid_[]     = "runid";
+static const char _runnables_[] = "runnables";
+static const char _runners_[]   = "runners";
+static const char _start_[]     = "start";
+static const char _state_[]     = "state";
+static const char _stop_[]      = "stop";
+static const char _terminate_[] = "terminate";
+static const char _uninstall_[] = "uninstall";
+static const char _uri_[]       = "uri";
+
+static const struct AFB_interface *interface;
 
 static struct jbus *jbus;
 
-static struct json_object *embed(AFB_request *request, const char *tag, struct json_object *obj)
+static struct json_object *embed(const char *tag, struct json_object *obj)
 {
        struct json_object *result;
 
        if (obj == NULL)
                result = NULL;
-       else if (!tag) {
-               request->errcode = MHD_HTTP_OK;
+       else if (!tag)
                result = obj;
-       }
        else {
                result = json_object_new_object();
                if (result == NULL) {
                        /* can't embed */
                        result = obj;
-                       request->errcode = MHD_HTTP_INTERNAL_SERVER_ERROR;
                }
                else {
                        /* TODO why is json-c not returning a status? */
                        json_object_object_add(result, tag, obj);
-                       request->errcode = MHD_HTTP_OK;
                }
        }
        return result;
 }
 
-static struct json_object *call_void(AFB_request *request, AFB_PostItem *item)
+static void embed_call_void(struct afb_req request, const char *method)
 {
-       struct json_object *obj = jbus_call_sj_sync(jbus, request->method, "true");
-       if (verbose)
-               fprintf(stderr, "(afm-main-plugin) call_void: true -> %s\n", obj ? json_object_to_json_string(obj) : "NULL");
-       request->errcode = obj ? MHD_HTTP_OK : MHD_HTTP_FAILED_DEPENDENCY;
-       return obj;
+       struct json_object *obj = jbus_call_sj_sync(jbus, method, "true");
+       if (interface->verbose)
+               fprintf(stderr, "(afm-main-plugin) %s(true) -> %s\n", method, obj ? json_object_to_json_string(obj) : "NULL");
+       if (obj == NULL) {
+               afb_req_fail(request, "failed", "framework daemon failure");
+               return;
+       }
+       obj = embed(method, obj);
+       if (obj == NULL) {
+               afb_req_fail(request, "failed", "framework daemon failure");
+               return;
+       }
+       afb_req_success(request, obj, NULL);
 }
 
-static struct json_object *call_appid(AFB_request *request, AFB_PostItem *item)
+static void call_appid(struct afb_req request, const char *method)
 {
        struct json_object *obj;
        char *sid;
-       const char *id = getQueryValue(request, _id_);
+       const char *id = afb_req_argument(request, _id_);
        if (id == NULL) {
-               request->errcode = MHD_HTTP_BAD_REQUEST;
-               return NULL;
+               afb_req_fail(request, "bad-request", "missing 'id'");
+               return;
        }
-       if (0 >= asprintf(&sid, "\"%s\"", id)) {
-               request->errcode = MHD_HTTP_INTERNAL_SERVER_ERROR;
-               return NULL;
+       if (asprintf(&sid, "\"%s\"", id) <= 0) {
+               afb_req_fail(request, "server-error", "out of memory");
+               return;
        }
-       obj = jbus_call_sj_sync(jbus, request->method, sid);
-       if (verbose)
-               fprintf(stderr, "(afm-main-plugin) call_appid: %s -> %s\n", sid, obj ? json_object_to_json_string(obj) : "NULL");
+       obj = jbus_call_sj_sync(jbus, method, sid);
+       if (interface->verbose)
+               fprintf(stderr, "(afm-main-plugin) %s(%s) -> %s\n", method, sid, obj ? json_object_to_json_string(obj) : "NULL");
        free(sid);
-       request->errcode = obj ? MHD_HTTP_OK : MHD_HTTP_FAILED_DEPENDENCY;
-       return obj;
+       if (obj == NULL) {
+               afb_req_fail(request, "failed", "framework daemon failure");
+               return;
+       }
+       afb_req_success(request, obj, NULL);
 }
 
-static struct json_object *call_runid(AFB_request *request, AFB_PostItem *item)
+static void call_runid(struct afb_req request, const char *method)
 {
        struct json_object *obj;
-       const char *id = getQueryValue(request, _runid_);
+       const char *id = afb_req_argument(request, _runid_);
        if (id == NULL) {
-               request->errcode = MHD_HTTP_BAD_REQUEST;
-               return NULL;
+               afb_req_fail(request, "bad-request", "missing 'runid'");
+               return;
+       }
+       obj = jbus_call_sj_sync(jbus, method, id);
+       if (interface->verbose)
+               fprintf(stderr, "(afm-main-plugin) %s(%s) -> %s\n", method, id,
+                               obj ? json_object_to_json_string(obj) : "NULL");
+       if (obj == NULL) {
+               afb_req_fail(request, "failed", "framework daemon failure");
+               return;
        }
-       obj = jbus_call_sj_sync(jbus, request->method, id);
-       if (verbose)
-               fprintf(stderr, "(afm-main-plugin) call_runid: %s -> %s\n", id, obj ? json_object_to_json_string(obj) : "NULL");
-       request->errcode = obj ? MHD_HTTP_OK : MHD_HTTP_FAILED_DEPENDENCY;
-       return obj;
+       afb_req_success(request, obj, NULL);
+}
+
+
+/************************** entries ******************************/
+
+static void runnables(struct afb_req request)
+{
+       embed_call_void(request, _runnables_);
 }
 
-static struct json_object *call_void__runnables(AFB_request *request, AFB_PostItem *item)
+static void detail(struct afb_req request)
 {
-       return embed(request, _runnables_, call_void(request, item));
+       call_appid(request, _detail_);
 }
 
-static struct json_object *call_start(AFB_request *request, AFB_PostItem *item)
+static void start(struct afb_req request)
 {
-       struct json_object *resp;
+       struct json_object *obj;
        const char *id, *mode;
        char *query;
        int rc;
 
        /* get the id */
-       id = getQueryValue(request, _id_);
+       id = afb_req_argument(request, _id_);
        if (id == NULL) {
-               request->errcode = MHD_HTTP_BAD_REQUEST;
-               return NULL;
+               afb_req_fail(request, "bad-request", "missing 'id'");
+               return;
        }
        /* get the mode */
-       mode = getQueryValue(request, _mode_);
+       mode = afb_req_argument(request, _mode_);
        if (mode == NULL || !strcmp(mode, _auto_)) {
-               mode = request->config->mode == AFB_MODE_REMOTE ? _remote_ : _local_;
+               mode = interface->mode == AFB_MODE_REMOTE ? _remote_ : _local_;
        }
 
        /* create the query */
        rc = asprintf(&query, "{\"id\":\"%s\",\"mode\":\"%s\"}", id, mode);
        if (rc < 0) {
-               request->errcode = MHD_HTTP_INTERNAL_SERVER_ERROR;
-               return NULL;
+               afb_req_fail(request, "server-error", "out of memory");
+               return;
        }
 
        /* calls the service */
-       resp = jbus_call_sj_sync(jbus, _start_, query);
-       if (verbose)
-               fprintf(stderr, "(afm-main-plugin) call_start: %s -> %s\n", query, resp ? json_object_to_json_string(resp) : "NULL");
+       obj = jbus_call_sj_sync(jbus, _start_, query);
+       if (interface->verbose)
+               fprintf(stderr, "(afm-main-plugin) start(%s) -> %s\n", query, obj ? json_object_to_json_string(obj) : "NULL");
        free(query);
 
+       /* check status */
+       if (obj == NULL) {
+               afb_req_fail(request, "failed", "framework daemon failure");
+               return;
+       }
+
        /* embed if needed */
-       if (json_object_get_type(resp) == json_type_int)
-               resp = embed(request, _runid_, resp);
-       request->errcode = resp ? MHD_HTTP_OK : MHD_HTTP_FAILED_DEPENDENCY;
-       return resp;
+       if (json_object_get_type(obj) == json_type_int)
+               obj = embed(_runid_, obj);
+       afb_req_success(request, obj, NULL);
 }
 
-static struct json_object *call_void__runners(AFB_request *request, AFB_PostItem *item)
+static void terminate(struct afb_req request)
 {
-       return embed(request, _runners_, call_void(request, item));
+       call_runid(request, _terminate_);
 }
 
-static struct json_object *call_file__appid(AFB_request *request, AFB_PostItem *item)
-{
-       if (item == NULL) {
-               const char *filename = getPostPath(request);
-               if (filename != NULL) {
-                       struct json_object *obj;
-                       char *query;
-                       request->jresp = NULL;
-                       if (0 >= asprintf(&query, "\"%s\"", filename))
-                               request->errcode = MHD_HTTP_INTERNAL_SERVER_ERROR;
-                       else {
-                               obj = jbus_call_sj_sync(jbus, request->method, query);
-                               if (verbose)
-                                       fprintf(stderr, "(afm-main-plugin) call_file_appid: %s -> %s\n", query, obj ? json_object_to_json_string(obj) : "NULL");
-                               free(query);
-                               if (obj)
-                                       request->jresp = embed(request, _id_, obj);
-                               else
-                                       request->errcode = MHD_HTTP_FAILED_DEPENDENCY;
-                       }
-                       unlink(filename);
-               }
+static void stop(struct afb_req request)
+{
+       call_runid(request, _stop_);
+}
+
+static void continue_(struct afb_req request)
+{
+       call_runid(request, _continue_);
+}
+
+static void runners(struct afb_req request)
+{
+       embed_call_void(request, _runners_);
+}
+
+static void state(struct afb_req request)
+{
+       call_runid(request, _state_);
+}
+
+static void install(struct afb_req request)
+{
+       struct json_object *obj;
+       char *query;
+       const char *filename;
+       struct afb_arg arg;
+
+       /* get the argument */
+       arg = afb_req_get(request, "widget");
+       filename = arg.value;
+       if (filename == NULL || !arg.is_file) {
+               afb_req_fail(request, "bad-request", "missing 'widget' file");
+               return;
+       }
+
+       /* makes the query */
+       if (0 >= asprintf(&query, "\"%s\"", filename)) {
+               afb_req_fail(request, "server-error", "out of memory");
+               return;
        }
-       return getPostFile (request, item, "/tmp/upload");
+
+       obj = jbus_call_sj_sync(jbus, _install_, query);
+       if (interface->verbose)
+               fprintf(stderr, "(afm-main-plugin) install(%s) -> %s\n", query, obj ? json_object_to_json_string(obj) : "NULL");
+       free(query);
+
+       /* check status */
+       if (obj == NULL) {
+               afb_req_fail(request, "failed", "framework daemon failure");
+               return;
+       }
+
+       /* embed if needed */
+       obj = embed(_id_, obj);
+       afb_req_success(request, obj, NULL);
 }
 
-static AFB_restapi plug_apis[] =
-{
-       {_runnables_, AFB_SESSION_CHECK, (AFB_apiCB)call_void__runnables,  "Get list of runnable applications"},
-       {_detail_   , AFB_SESSION_CHECK, (AFB_apiCB)call_appid, "Get the details for one application"},
-       {_start_    , AFB_SESSION_CHECK, (AFB_apiCB)call_start, "Start an application"},
-       {_terminate_, AFB_SESSION_CHECK, (AFB_apiCB)call_runid, "Terminate a running application"},
-       {_stop_     , AFB_SESSION_CHECK, (AFB_apiCB)call_runid, "Stop (pause) a running application"},
-       {_continue_ , AFB_SESSION_CHECK, (AFB_apiCB)call_runid, "Continue (resume) a stopped application"},
-       {_runners_  , AFB_SESSION_CHECK, (AFB_apiCB)call_void__runners,  "Get the list of running applications"},
-       {_state_    , AFB_SESSION_CHECK, (AFB_apiCB)call_runid, "Get the state of a running application"},
-       {_install_  , AFB_SESSION_CHECK, (AFB_apiCB)call_file__appid,  "Install an application using a widget file"},
-       {_uninstall_, AFB_SESSION_CHECK, (AFB_apiCB)call_appid, "Uninstall an application"},
+static void uninstall(struct afb_req request)
+{
+       call_appid(request, _uninstall_);
+}
+
+static const struct AFB_restapi plug_apis[] =
+{
+       {_runnables_, AFB_SESSION_CHECK, runnables,  "Get list of runnable applications"},
+       {_detail_   , AFB_SESSION_CHECK, detail, "Get the details for one application"},
+       {_start_    , AFB_SESSION_CHECK, start, "Start an application"},
+       {_terminate_, AFB_SESSION_CHECK, terminate, "Terminate a running application"},
+       {_stop_     , AFB_SESSION_CHECK, stop, "Stop (pause) a running application"},
+       {_continue_ , AFB_SESSION_CHECK, continue_, "Continue (resume) a stopped application"},
+       {_runners_  , AFB_SESSION_CHECK, runners,  "Get the list of running applications"},
+       {_state_    , AFB_SESSION_CHECK, state, "Get the state of a running application"},
+       {_install_  , AFB_SESSION_CHECK, install,  "Install an application using a widget file"},
+       {_uninstall_, AFB_SESSION_CHECK, uninstall, "Uninstall an application"},
        { NULL, 0, NULL, NULL }
 };
 
-static AFB_plugin plug_desc = {
+static const struct AFB_plugin plug_desc = {
        .type = AFB_PLUGIN_JSON,
        .info = "Application Framework Master Service",
        .prefix = "afm-main",
        .apis = plug_apis
 };
 
-AFB_plugin *pluginRegister()
+const struct AFB_plugin *pluginRegister(const struct AFB_interface *itf)
 {
+       interface = itf;
+
        jbus = create_jbus_session("/org/AGL/afm/user");
         if (jbus)
                return &plug_desc;
index cda6abb..3fa43ad 100644 (file)
@@ -75,7 +75,7 @@ static void myCreate (struct afb_req request)
     ctx->count = 0;
     ctx->abcd  = "SomeThingUseful";        
 
-    *request.context = ctx;
+    request.context = ctx;
     afb_req_success_f(request, NULL, "SUCCESS: create client context for plugin [%s]", handle->anythingYouWant);
 }
 
@@ -86,7 +86,7 @@ static void myCreate (struct afb_req request)
 static void myAction (struct afb_req request)
 {
     MyPluginHandleT  *handle = (MyPluginHandleT*) &global_handle;
-    MyClientContextT *ctx = (MyClientContextT*) *request.context;
+    MyClientContextT *ctx = (MyClientContextT*) request.context;
     
     // store something in our plugin private client context
     ctx->count++;
@@ -100,7 +100,7 @@ static void myAction (struct afb_req request)
 static void myClose (struct afb_req request)
 {
     MyPluginHandleT  *handle = (MyPluginHandleT*) &global_handle;
-    MyClientContextT *ctx = (MyClientContextT*) *request.context;
+    MyClientContextT *ctx = (MyClientContextT*) request.context;
     
     // store something in our plugin private client context
     ctx->count++;
@@ -132,8 +132,9 @@ static const struct AFB_plugin plugin_desc = {
        .freeCtxCB = (void*)freeCtxCB
 };
 
-const struct AFB_plugin *pluginRegister ()
+const struct AFB_plugin *pluginRegister (const struct AFB_interface *itf)
 {
+       global_handle.anythingYouWant = "anythingYouWant";
        return &plugin_desc;
 }
 
index 4f0af71..c60cc70 100644 (file)
@@ -85,7 +85,6 @@ static void pingBug (struct afb_req request)
 {
     int a,b,c;
     
-    fprintf (stderr, "Use --timeout=10 to trap error\n");
     b=4;
     c=0;
     a=b/c;
@@ -128,7 +127,7 @@ static const struct AFB_plugin plugin_desc = {
        .apis = pluginApis
 };
 
-const struct AFB_plugin *pluginRegister ()
+const struct AFB_plugin *pluginRegister (const struct AFB_interface *itf)
 {
        return &plugin_desc;
 }
index 65c18d2..04945a8 100644 (file)
@@ -36,7 +36,7 @@ static void clientContextCreate (struct afb_req request)
     json_object *jresp;
 
     // add an application specific client context to session
-    *request.context = malloc (sizeof (MyClientApplicationHandle));
+    request.context = malloc (sizeof (MyClientApplicationHandle));
     
     // Send response to UI
     jresp = json_object_new_object();               
@@ -118,7 +118,7 @@ static const struct AFB_plugin plugin_desc = {
        .freeCtxCB = clientContextFree
 };
 
-const struct AFB_plugin *pluginRegister ()
+const struct AFB_plugin *pluginRegister (const struct AFB_interface *itf)
 {
        return &plugin_desc;
 }
index 0a04ed7..735649c 100644 (file)
 
 #include "afb-plugin.h"
 #include "afb-req-itf.h"
+#include "session.h"
 #include "afb-apis.h"
 
 struct api_desc {
-       AFB_plugin *plugin;     /* descriptor */
+       struct AFB_plugin *plugin;      /* descriptor */
        size_t prefixlen;
        const char *prefix;
        void *handle;           /* context of dlopen */
+       struct AFB_interface *interface;
 };
 
 static int api_timeout = 15;
@@ -73,50 +75,14 @@ void afb_apis_free_context(int apiidx, void *context)
                free(context);
 }
 
-/*
-const struct AFB_restapi *afb_apis_get(int apiidx, int verbidx)
-{
-       assert(0 <= apiidx && apiidx < apis_count);
-       return &apis_array[apiidx].plugin->apis[verbidx];
-}
-
-int afb_apis_get_verbidx(int apiidx, const char *name)
-{
-       const struct AFB_restapi *apis;
-       int idx;
-
-       assert(0 <= apiidx && apiidx < apis_count);
-       apis = apis_array[apiidx].plugin->apis;
-       for (idx = 0 ; apis[idx].name ; idx++)
-               if (!strcasecmp(apis[idx].name, name))
-                       return idx;
-       return -1;
-}
-*/
-
-int afb_apis_get_apiidx(const char *prefix, size_t length)
-{
-       int i;
-       const struct api_desc *a;
-
-       if (!length)
-               length = strlen(prefix);
-
-       for (i = 0 ; i < apis_count ; i++) {
-               a = &apis_array[i];
-               if (a->prefixlen == length && !strcasecmp(a->prefix, prefix))
-                       return i;
-       }
-       return -1;
-}
-
 int afb_apis_add_plugin(const char *path)
 {
        struct api_desc *apis;
-       AFB_plugin *plugin;
-       AFB_plugin *(*pluginRegisterFct) (void);
+       struct AFB_plugin *plugin;
+       struct AFB_plugin *(*pluginRegisterFct) (const struct AFB_interface *interface);
+       struct AFB_interface *interface;
        void *handle;
-       size_t len;
+       int i;
 
        // This is a loadable library let's check if it's a plugin
        handle = dlopen(path, RTLD_NOW | RTLD_LOCAL);
@@ -142,36 +108,46 @@ int afb_apis_add_plugin(const char *path)
        }
        apis_array = apis;
 
+       /* allocates the interface */
+       interface = calloc(1, sizeof *interface);
+       if (interface == NULL) {
+               fprintf(stderr, "ERROR: plugin [%s] memory missing. continuing...\n", path);
+               goto error2;
+       }
+       interface->verbose = 0;
+       interface->mode = AFB_MODE_LOCAL;
+
        /* init the plugin */
-       plugin = pluginRegisterFct();
+       plugin = pluginRegisterFct(interface);
        if (plugin == NULL) {
                fprintf(stderr, "ERROR: plugin [%s] register function failed. continuing...\n", path);
-               goto error2;
+               goto error3;
        }
 
        /* check the returned structure */
        if (plugin->type != AFB_PLUGIN_JSON) {
                fprintf(stderr, "ERROR: plugin [%s] invalid type %d...\n", path, plugin->type);
-               goto error2;
+               goto error3;
        }
        if (plugin->prefix == NULL || *plugin->prefix == 0) {
                fprintf(stderr, "ERROR: plugin [%s] bad prefix...\n", path);
-               goto error2;
+               goto error3;
        }
        if (plugin->info == NULL || *plugin->info == 0) {
                fprintf(stderr, "ERROR: plugin [%s] bad description...\n", path);
-               goto error2;
+               goto error3;
        }
        if (plugin->apis == NULL) {
                fprintf(stderr, "ERROR: plugin [%s] no APIs...\n", path);
-               goto error2;
+               goto error3;
        }
 
        /* check previously existing plugin */
-       len = strlen(plugin->prefix);
-       if (afb_apis_get_apiidx(plugin->prefix, len) >= 0) {
-               fprintf(stderr, "ERROR: plugin [%s] prefix %s duplicated...\n", path, plugin->prefix);
-               goto error2;
+       for (i = 0 ; i < apis_count ; i++) {
+               if (!strcasecmp(apis_array[i].prefix, plugin->prefix)) {
+                       fprintf(stderr, "ERROR: plugin [%s] prefix %s duplicated...\n", path, plugin->prefix);
+                       goto error2;
+               }
        }
 
        /* record the plugin */
@@ -179,13 +155,16 @@ int afb_apis_add_plugin(const char *path)
                fprintf(stderr, "Loading plugin[%lu] prefix=[%s] info=%s\n", (unsigned long)apis_count, plugin->prefix, plugin->info);
        apis = &apis_array[apis_count];
        apis->plugin = plugin;
-       apis->prefixlen = len;
+       apis->prefixlen = strlen(plugin->prefix);
        apis->prefix = plugin->prefix;
        apis->handle = handle;
+       apis->interface = interface;
        apis_count++;
 
        return 0;
 
+error3:
+       free(interface);
 error2:
        dlclose(handle);
 error:
@@ -330,46 +309,33 @@ static void trapping_handle(struct afb_req req, void(*cb)(struct afb_req))
        error_handler = older;
 }
 
-static void handle(struct afb_req req, int idxapi, const struct AFB_restapi *verb)
+static void handle(struct afb_req req, const struct AFB_restapi *verb)
 {
        switch(verb->session) {
        case AFB_SESSION_CREATE:
-               /*
-               req.context = afb_req_session_create(req, idxapi);
-               if (req.context == NULL)
+               if (!afb_req_session_create(req))
                        return;
                break;
-               */
        case AFB_SESSION_RENEW:
-               /*
-               req.context = afb_req_session_check(req, idxapi, 1);
-               if (req.context == NULL)
+               if (!afb_req_session_check(req, 1))
                        return;
-               */
                break;
        case AFB_SESSION_CLOSE:
        case AFB_SESSION_CHECK:
-               /*
-               req.context = afb_req_session_check(req, idxapi, 1);
-               if (req.context == NULL)
+               if (!afb_req_session_check(req, 0))
                        return;
-               */
                break;
        case AFB_SESSION_NONE:
        default:
-               req.context = NULL;
                break;
        }
        trapping_handle(req, verb->callback);
 
-       if (verb->session == AFB_SESSION_CLOSE) {
-               /*
+       if (verb->session == AFB_SESSION_CLOSE)
                afb_req_session_close(req);
-               */
-       }
 }
 
-int afb_apis_handle(struct afb_req req, const char *api, size_t lenapi, const char *verb, size_t lenverb)
+int afb_apis_handle(struct afb_req req, struct AFB_clientCtx *context, const char *api, size_t lenapi, const char *verb, size_t lenverb)
 {
        int i, j;
        const struct api_desc *a;
@@ -381,7 +347,9 @@ int afb_apis_handle(struct afb_req req, const char *api, size_t lenapi, const ch
                        v = a->plugin->apis;
                        for (j = 0 ; v->name ; j++, v++) {
                                if (!strncasecmp(v->name, verb, lenverb) && !v->name[lenverb]) {
-                                       handle(req, i, v);
+                                       req.context = context->contexts[i];
+                                       handle(req, v);
+                                       context->contexts[i] = req.context;
                                        return 1;
                                }
                        }
index dc4401c..9127e6d 100644 (file)
@@ -20,12 +20,6 @@ extern int afb_apis_count();
 
 extern void afb_apis_free_context(int apiidx, void *context);
 
-extern const struct AFB_restapi *afb_apis_get(int apiidx, int verbidx);
-
-extern int afb_apis_get_verbidx(int apiidx, const char *name);
-
-extern int afb_apis_get_apiidx(const char *prefix, size_t length);
-
 extern int afb_apis_add_plugin(const char *path);
 
 extern int afb_apis_add_directory(const char *path);
@@ -35,5 +29,6 @@ extern int afb_apis_add_path(const char *path);
 extern int afb_apis_add_pathset(const char *pathset);
 
 struct afb_req;
-extern int afb_apis_handle(struct afb_req req, const char *api, size_t lenapi, const char *verb, size_t lenverb);
+struct AFB_clientCtx;
+extern int afb_apis_handle(struct afb_req req, struct AFB_clientCtx *context, const char *api, size_t lenapi, const char *verb, size_t lenverb);
 
index e146bcb..16c235a 100644 (file)
 #include "afb-method.h"
 #include "afb-req-itf.h"
 #include "afb-hreq.h"
+#include "session.h"
 
 #define SIZE_RESPONSE_BUFFER   8000
 
 static char empty_string[] = "";
 
+static const char uuid_header[] = "x-afb-uuid";
+static const char uuid_arg[] = "uuid";
+static const char uuid_cookie[] = "uuid";
+
+static const char token_header[] = "x-afb-token";
+static const char token_arg[] = "token";
+static const char token_cookie[] = "token";
+
+
 struct hreq_data {
        struct hreq_data *next;
        char *key;
@@ -48,15 +58,19 @@ static struct afb_arg req_get(struct afb_hreq *hreq, const char *name);
 static void req_iterate(struct afb_hreq *hreq, int (*iterator)(void *closure, struct afb_arg arg), void *closure);
 static void req_fail(struct afb_hreq *hreq, const char *status, const char *info);
 static void req_success(struct afb_hreq *hreq, json_object *obj, const char *info);
+static int req_session_create(struct afb_hreq *hreq);
+static int req_session_check(struct afb_hreq *hreq, int refresh);
+static void req_session_close(struct afb_hreq *hreq);
 
 static const struct afb_req_itf afb_hreq_itf = {
        .get = (void*)req_get,
        .iterate = (void*)req_iterate,
        .fail = (void*)req_fail,
-       .success = (void*)req_success
+       .success = (void*)req_success,
+       .session_create = (void*)req_session_create,
+       .session_check = (void*)req_session_check,
+       .session_close = (void*)req_session_close
 };
-       void (*fail)(void *data, const char *status, const char *info);
-       void (*success)(void *data, json_object *obj, const char *info);
 
 static struct hreq_data *get_data(struct afb_hreq *hreq, const char *key, int create)
 {
@@ -121,8 +135,25 @@ static int validsubpath(const char *subpath)
        return 1;
 }
 
+void afb_hreq_free(struct afb_hreq *hreq)
+{
+       struct hreq_data *data;
+       if (hreq != NULL) {
+               if (hreq->postform != NULL)
+                       MHD_destroy_post_processor(hreq->postform);
+               for (data = hreq->data; data; data = hreq->data) {
+                       hreq->data = data->next;
+                       free(data->key);
+                       free(data->value);
+                       free(data);
+               }
+               ctxClientPut(hreq->context);
+               free(hreq);
+       }
+}
+
 /*
- * Removes the 'prefix' of 'length' frome the tail of 'hreq'
+ * Removes the 'prefix' of 'length' from the tail of 'hreq'
  * if and only if the prefix exists and is terminated by a leading
  * slash
  */
@@ -430,17 +461,6 @@ static void req_iterate(struct afb_hreq *hreq, int (*iterator)(void *closure, st
        MHD_get_connection_values (hreq->connection, MHD_GET_ARGUMENT_KIND, (void*)_iterargs_, &id);
 }
 
-void afb_hreq_drop_data(struct afb_hreq *hreq)
-{
-       struct hreq_data *data = hreq->data;
-       while (data) {
-               hreq->data = data->next;
-               free(data->key);
-               free(data->value);
-               free(data);
-               data = hreq->data;
-       }
-}
 static ssize_t send_json_cb(json_object *obj, uint64_t pos, char *buf, size_t max)
 {
        ssize_t len = stpncpy(buf, json_object_to_json_string(obj)+pos, max) - buf;
@@ -461,6 +481,10 @@ static void req_reply(struct afb_hreq *hreq, unsigned retcode, const char *statu
                json_object_object_add(request, "info", json_object_new_string(info));
        if (resp)
                json_object_object_add(root, "response", resp);
+       if (hreq->context) {
+               json_object_object_add(request, uuid_arg, json_object_new_string(hreq->context->uuid));
+               json_object_object_add(request, token_arg, json_object_new_string(hreq->context->token));
+       }
 
        response = MHD_create_response_from_callback(MHD_SIZE_UNKNOWN, SIZE_RESPONSE_BUFFER, (void*)send_json_cb, root, (void*)json_object_put);
        MHD_queue_response(hreq->connection, retcode, response);
@@ -477,3 +501,64 @@ static void req_success(struct afb_hreq *hreq, json_object *obj, const char *inf
        req_reply(hreq, MHD_HTTP_OK, "success", info, obj);
 }
 
+struct AFB_clientCtx *afb_hreq_context(struct afb_hreq *hreq)
+{
+       const char *uuid;
+
+       if (hreq->context == NULL) {
+               uuid = afb_hreq_get_header(hreq, uuid_header);
+               if (uuid == NULL)
+                       uuid = afb_hreq_get_argument(hreq, uuid_arg);
+               if (uuid == NULL)
+                       uuid = afb_hreq_get_cookie(hreq, uuid_cookie);
+               hreq->context = ctxClientGet(uuid);
+       }
+       return hreq->context;
+}
+
+static int req_session_create(struct afb_hreq *hreq)
+{
+       struct AFB_clientCtx *context = afb_hreq_context(hreq);
+       if (context == NULL)
+               return 0;
+       if (context->created)
+               return 0;
+       return req_session_check(hreq, 1);
+}
+
+static int req_session_check(struct afb_hreq *hreq, int refresh)
+{
+       const char *token;
+
+       struct AFB_clientCtx *context = afb_hreq_context(hreq);
+
+       if (context == NULL)
+               return 0;
+
+       token = afb_hreq_get_header(hreq, token_header);
+       if (token == NULL)
+               token = afb_hreq_get_argument(hreq, token_arg);
+       if (token == NULL)
+               token = afb_hreq_get_cookie(hreq, token_cookie);
+       if (token == NULL)
+               return 0;
+
+       if (!ctxTokenCheck (context, token))
+               return 0;
+
+       if (refresh) {
+               ctxTokenNew (context);
+       }
+
+       return 1;
+}
+
+static void req_session_close(struct afb_hreq *hreq)
+{
+       struct AFB_clientCtx *context = afb_hreq_context(hreq);
+       if (context != NULL)
+               ctxClientClose(context);
+}
+
+
+
index fb914f1..cf23638 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 struct AFB_session;
+struct AFB_clientCtx;
 
 struct afb_hreq {
        struct AFB_session *session;
@@ -31,6 +32,8 @@ struct afb_hreq {
        struct hreq_data *data;
 };
 
+extern void afb_hreq_free(struct afb_hreq *request);
+
 extern int afb_hreq_unprefix(struct afb_hreq *request, const char *prefix, size_t length);
 
 extern int afb_hreq_valid_tail(struct afb_hreq *request);
@@ -59,5 +62,4 @@ extern void afb_hreq_post_end(struct afb_hreq *hreq);
 
 extern struct afb_req afb_hreq_to_req(struct afb_hreq *hreq);
 
-extern void afb_hreq_drop_data(struct afb_hreq *hreq);
-
+extern struct AFB_clientCtx *afb_hreq_context(struct afb_hreq *hreq);
index 9235bf8..c767de7 100644 (file)
 #include "afb-hreq.h"
 #include "afb-websock.h"
 #include "afb-apis.h"
-#include "session.h"
 #include "afb-req-itf.h"
 
 #define JSON_CONTENT  "application/json"
 #define FORM_CONTENT  MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA
 
+
 struct afb_hsrv_handler {
        struct afb_hsrv_handler *next;
        const char *prefix;
@@ -137,25 +137,6 @@ int afb_hsrv_add_handler(
        return 1;
 }
 
-static const char uuid_header[] = "x-afb-uuid";
-static const char uuid_arg[] = "uuid";
-static const char uuid_cookie[] = "uuid";
-
-static struct AFB_clientCtx *afb_hreq_context(struct afb_hreq *hreq)
-{
-       const char *uuid;
-
-       if (hreq->context == NULL) {
-               uuid = afb_hreq_get_header(hreq, uuid_header);
-               if (uuid == NULL)
-                       uuid = afb_hreq_get_argument(hreq, uuid_arg);
-               if (uuid == NULL)
-                       uuid = afb_hreq_get_cookie(hreq, uuid_cookie);
-               hreq->context = ctxClientGet(uuid);
-       }
-       return hreq->context;
-}
-
 static int afb_hreq_websocket_switch(struct afb_hreq *hreq, void *data)
 {
        int later;
@@ -179,6 +160,7 @@ static int afb_hreq_rest_api(struct afb_hreq *hreq, void *data)
 {
        const char *api, *verb;
        size_t lenapi, lenverb;
+       struct AFB_clientCtx *context;
 
        api = &hreq->tail[strspn(hreq->tail, "/")];
        lenapi = strcspn(api, "/");
@@ -189,7 +171,8 @@ static int afb_hreq_rest_api(struct afb_hreq *hreq, void *data)
        if (!(*api && *verb && lenapi && lenverb))
                return 0;
 
-       return afb_apis_handle(afb_hreq_to_req(hreq), api, lenapi, verb, lenverb);
+       context = afb_hreq_context(hreq);
+       return afb_apis_handle(afb_hreq_to_req(hreq), context, api, lenapi, verb, lenverb);
 }
 
 static int handle_alias(struct afb_hreq *hreq, void *data)
@@ -376,18 +359,11 @@ internal_error:
 static void end_handler(void *cls, struct MHD_Connection *connection, void **recordreq,
                        enum MHD_RequestTerminationCode toe)
 {
-       AFB_session *session;
        struct afb_hreq *hreq;
 
-       session = cls;
        hreq = *recordreq;
 
-       if (hreq != NULL) {
-               if (hreq->postform != NULL)
-                       MHD_destroy_post_processor(hreq->postform);
-               afb_hreq_drop_data(hreq);
-               free(hreq);
-       }
+       afb_hreq_free(hreq);
 }
 
 static int new_client_handler(void *cls, const struct sockaddr *addr, socklen_t addrlen)
index a1cac53..39ae318 100644 (file)
@@ -66,62 +66,11 @@ typedef enum  { AFB_FALSE, AFB_TRUE, AFB_FATAL, AFB_FAIL, AFB_WARNING, AFB_EMPTY
 
 
 
-#if 0
-
-// Plugin Type
-enum  AFB_pluginE
-{
-       AFB_PLUGIN_JSON = 123456789,
-       AFB_PLUGIN_JSCRIPT = 987654321,
-       AFB_PLUGIN_RAW = 987123546
-};
-
-// Enum for Session/Token/Authentication middleware
-enum AFB_sessionE
-{
-       AFB_SESSION_NONE,
-       AFB_SESSION_CREATE,
-       AFB_SESSION_CLOSE,
-       AFB_SESSION_RENEW,
-       AFB_SESSION_CHECK
-};
-
-// API definition
-struct AFB_restapi
-{
-       const char *name;
-       enum AFB_sessionE session;
-       struct json_object* (*callback)();
-       const char *info;
-};
-
-// Plugin definition
-struct AFB_plugin
-{
-       enum AFB_pluginE type;  
-       const char *info;
-       const char *prefix;
-       const struct AFB_restapi *apis;
-       void (*freeCtxCB)(void*);  // callback to free application context [null for standard free]
-};
-
-typedef enum AFB_pluginE AFB_pluginE;
-typedef enum AFB_sessionE AFB_sessionE;
-typedef struct json_object* (*AFB_apiCB)();
-typedef void (*AFB_freeCtxCB)(void*);
-typedef struct AFB_restapi AFB_restapi;
-typedef struct AFB_plugin AFB_plugin;
-
-
-#endif
-
-
-
 
 
 
 
-typedef enum  {AFB_MODE_LOCAL=0, AFB_MODE_REMOTE, AFB_MODE_GLOBAL} AFB_Mode;
+enum AFB_Mode;
 
 
 typedef struct {
@@ -144,7 +93,7 @@ struct AFB_config
   int  cacheTimeout;
   int  apiTimeout;
   int  cntxTimeout;        // Client Session Context timeout
-  AFB_Mode mode;           // mode of listening
+  int mode;           // mode of listening
   AFB_aliasdir *aliasdir;  // alias mapping for icons,apps,...
 };
 
index 2401043..95b5a65 100644 (file)
 #include <sys/stat.h>
 #include <sys/types.h>
 
-/*
-#include <pwd.h>
-#include <pthread.h>
-*/
+#include "afb-plugin.h"
 
 #include "local-def.h"
 #include "afb-apis.h"
index ad41123..e9cf298 100644 (file)
 #include <uuid/uuid.h>
 #include <assert.h>
 
-
-/*
-#include <dirent.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <search.h>
-#include <assert.h>
-*/
-
 #include "afb-apis.h"
 #include "session.h"
 
@@ -47,7 +37,7 @@
 // Session UUID are store in a simple array [for 10 sessions this should be enough]
 static struct {
   pthread_mutex_t mutex;          // declare a mutex to protect hash table
-  AFB_clientCtx **store;          // sessions store
+  struct AFB_clientCtx **store;          // sessions store
   int count;                      // current number of sessions
   int max;
   int timeout;
@@ -55,31 +45,28 @@ static struct {
   const char *initok;
 } sessions;
 
-static const char key_uuid[] = "uuid";
-static const char key_token[] = "token";
-
 // Free context [XXXX Should be protected again memory abort XXXX]
-static void ctxUuidFreeCB (AFB_clientCtx *client)
+static void ctxUuidFreeCB (struct AFB_clientCtx *client)
 {
-    int idx;
+       int idx;
 
-    // If application add a handle let's free it now
-    if (client->contexts != NULL) {
+       // If application add a handle let's free it now
+       assert (client->contexts != NULL);
 
-        // Free client handle with a standard Free function, with app callback or ignore it
-        for (idx=0; idx < sessions.apicount; idx ++) {
-            if (client->contexts[idx] != NULL) {
-               afb_apis_free_context(idx, client->contexts[idx]);
-            }
-        }
-    }
+       // Free client handle with a standard Free function, with app callback or ignore it
+       for (idx=0; idx < sessions.apicount; idx ++) {
+               if (client->contexts[idx] != NULL) {
+                       afb_apis_free_context(idx, client->contexts[idx]);
+                       client->contexts[idx] = NULL;
+               }
+       }
 }
 
 // Create a new store in RAM, not that is too small it will be automatically extended
 void ctxStoreInit (int nbSession, int timeout, int apicount, const char *initok)
 {
        // let's create as store as hashtable does not have any
-       sessions.store = calloc (1 + (unsigned)nbSession, sizeof(AFB_clientCtx));
+       sessions.store = calloc (1 + (unsigned)nbSession, sizeof(struct AFB_clientCtx));
        sessions.max = nbSession;
        sessions.timeout = timeout;
        sessions.apicount = apicount;
@@ -90,10 +77,10 @@ void ctxStoreInit (int nbSession, int timeout, int apicount, const char *initok)
        sessions.initok = initok;
 }
 
-static AFB_clientCtx *ctxStoreSearch (const char* uuid)
+static struct AFB_clientCtx *ctxStoreSearch (const char* uuid)
 {
     int  idx;
-    AFB_clientCtx *client;
+    struct AFB_clientCtx *client;
 
     assert (uuid != NULL);
 
@@ -111,7 +98,7 @@ found:
     return client;
 }
 
-static int ctxStoreDel (AFB_clientCtx *client)
+static int ctxStoreDel (struct AFB_clientCtx *client)
 {
     int idx;
     int status;
@@ -124,7 +111,6 @@ static int ctxStoreDel (AFB_clientCtx *client)
         if (sessions.store[idx] == client) {
                sessions.store[idx]=NULL;
                sessions.count--;
-               ctxUuidFreeCB (client);
                status = 1;
                goto deleted;
        }
@@ -135,7 +121,7 @@ deleted:
     return status;
 }
 
-static int ctxStoreAdd (AFB_clientCtx *client)
+static int ctxStoreAdd (struct AFB_clientCtx *client)
 {
     int idx;
     int status;
@@ -161,59 +147,65 @@ added:
 }
 
 // Check if context timeout or not
-static int ctxStoreTooOld (AFB_clientCtx *ctx, time_t now)
+static int ctxStoreTooOld (struct AFB_clientCtx *ctx, time_t now)
 {
-    return ctx->timeStamp <= now;
+    return ctx->expiration <= now;
 }
 
 // Loop on every entry and remove old context sessions.hash
-void ctxStoreGarbage ()
+static void ctxStoreCleanUp (time_t now)
 {
-    AFB_clientCtx *ctx;
-    long idx;
-    time_t now = NOW;
-
-    // Loop on Sessions Table and remove anything that is older than timeout
-    for (idx=0; idx < sessions.max; idx++) {
-        ctx = sessions.store[idx];
-        if (ctx != NULL && ctxStoreTooOld(ctx, now)) {
-            ctxStoreDel (ctx);
-        }
-    }
+       struct AFB_clientCtx *ctx;
+       long idx;
+
+       // Loop on Sessions Table and remove anything that is older than timeout
+       for (idx=0; idx < sessions.max; idx++) {
+               ctx = sessions.store[idx];
+               if (ctx != NULL && ctxStoreTooOld(ctx, now)) {
+                       ctxClientClose (ctx);
+               }
+       }
 }
 
 // This function will return exiting client context or newly created client context
-AFB_clientCtx *ctxClientGet (const char *uuid)
+struct AFB_clientCtx *ctxClientGet (const char *uuid)
 {
        uuid_t newuuid;
-       AFB_clientCtx *clientCtx;
+       struct AFB_clientCtx *clientCtx;
+       time_t now;
 
        /* search for an existing one not too old */
+       now = NOW;
+       ctxStoreCleanUp (now);
        clientCtx = uuid != NULL ? ctxStoreSearch (uuid) : NULL;
        if (clientCtx) {
-            if (!ctxStoreTooOld (clientCtx, NOW))
+               clientCtx->refcount++;
                return clientCtx;
-            ctxStoreDel (clientCtx);
         }
 
        /* mimic old behaviour */
        if (sessions.initok == NULL)
                return NULL;
 
-       /* cleanup before creating */
-       if(2 * sessions.count >= sessions.max)
-               ctxStoreGarbage();
+       /* check the uuid if given */
+       if (uuid != NULL && 1 + strlen(uuid) >= sizeof clientCtx->uuid)
+               return NULL;
 
        /* returns a new one */
-        clientCtx = calloc(1, sizeof(AFB_clientCtx)); // init NULL clientContext
+        clientCtx = calloc(1, sizeof(struct AFB_clientCtx)); // init NULL clientContext
        if (clientCtx != NULL) {
                clientCtx->contexts = calloc ((unsigned)sessions.apicount, sizeof (void*));
                if (clientCtx->contexts != NULL) {
                        /* generate the uuid */
-                       uuid_generate(newuuid);
-                       uuid_unparse_lower(newuuid, clientCtx->uuid);
-                       clientCtx->timeStamp = time(NULL) + sessions.timeout;
+                       if (uuid == NULL) {
+                               uuid_generate(newuuid);
+                               uuid_unparse_lower(newuuid, clientCtx->uuid);
+                       } else {
+                               strcpy(clientCtx->uuid, uuid);
+                       }
                        strcpy(clientCtx->token, sessions.initok);
+                       clientCtx->expiration = now + sessions.timeout;
+                       clientCtx->refcount = 1;
                        if (ctxStoreAdd (clientCtx))
                                return clientCtx;
                        free(clientCtx->contexts);
@@ -223,15 +215,28 @@ AFB_clientCtx *ctxClientGet (const char *uuid)
        return NULL;
 }
 
+void ctxClientPut(struct AFB_clientCtx *clientCtx)
+{
+       if (clientCtx != NULL) {
+               assert(clientCtx->refcount != 0);
+               --clientCtx->refcount;
+       }
+}
+
 // Free Client Session Context
-int ctxClientClose (AFB_clientCtx *clientCtx)
+void ctxClientClose (struct AFB_clientCtx *clientCtx)
 {
        assert(clientCtx != NULL);
-       return ctxStoreDel (clientCtx);
+       if (clientCtx->created) {
+               clientCtx->created = 0;
+               ctxUuidFreeCB (clientCtx);
+       }
+               if (clientCtx->refcount == 0)
+               ctxStoreDel (clientCtx);
 }
 
 // Sample Generic Ping Debug API
-int ctxTokenCheck (AFB_clientCtx *clientCtx, const char *token)
+int ctxTokenCheck (struct AFB_clientCtx *clientCtx, const char *token)
 {
        assert(clientCtx != NULL);
        assert(token != NULL);
@@ -239,8 +244,9 @@ int ctxTokenCheck (AFB_clientCtx *clientCtx, const char *token)
        // compare current token with previous one
        if (ctxStoreTooOld (clientCtx, NOW))
                return 0;
+
        if (!clientCtx->token[0] || 0 == strcmp (token, clientCtx->token)) {
-               clientCtx->timeStamp = time(NULL) + sessions.timeout;
+               clientCtx->created = 1; /* creates by default */
                return 1;
        }
 
@@ -249,7 +255,7 @@ int ctxTokenCheck (AFB_clientCtx *clientCtx, const char *token)
 }
 
 // generate a new token and update client context
-int ctxTokenNew (AFB_clientCtx *clientCtx)
+void ctxTokenNew (struct AFB_clientCtx *clientCtx)
 {
        uuid_t newuuid;
 
@@ -260,8 +266,6 @@ int ctxTokenNew (AFB_clientCtx *clientCtx)
        uuid_unparse_lower(newuuid, clientCtx->token);
 
        // keep track of time for session timeout and further clean up
-       clientCtx->timeStamp = time(NULL) + sessions.timeout;
-
-       return 1;
+       clientCtx->expiration = NOW + sessions.timeout;
 }
 
index 9b54179..28f2599 100644 (file)
 
 struct AFB_clientCtx
 {
-  time_t timeStamp;     // last time token was refresh
-  void **contexts;      // application specific context [one per plugin]]
-  char uuid[37];        // long term authentication of remote client
-  char token[37];       // short term authentication of remote client
+       time_t expiration;    // expiration time of the token
+       int created;
+       unsigned refcount;
+       void **contexts;      // application specific context [one per plugin]
+       char uuid[37];        // long term authentication of remote client
+       char token[37];       // short term authentication of remote client
 };
-typedef struct AFB_clientCtx AFB_clientCtx;
-
-extern void ctxStoreGarbage ();
 
 extern void ctxStoreInit (int nbSession, int timeout, int apicount, const char *initok);
 
-extern AFB_clientCtx *ctxClientGet (const char *uuid);
-extern int ctxClientClose (AFB_clientCtx *clientCtx);
-extern int ctxTokenCheck (AFB_clientCtx *clientCtx, const char *token);
-extern int ctxTokenNew (AFB_clientCtx *clientCtx);
+extern struct AFB_clientCtx *ctxClientGet (const char *uuid);
+extern void ctxClientPut(struct AFB_clientCtx *clientCtx);
+extern void ctxClientClose (struct AFB_clientCtx *clientCtx);
+extern int ctxTokenCheck (struct AFB_clientCtx *clientCtx, const char *token);
+extern void ctxTokenNew (struct AFB_clientCtx *clientCtx);