From 46d9538587a3521caa1e3b20bf337a53ed400777 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jos=C3=A9=20Bollo?= Date: Tue, 19 Apr 2016 13:23:08 +0200 Subject: [PATCH] refactoring context handling MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Change-Id: I0e5a900efbd94b66f309ff4d0d49a6406585203f Signed-off-by: José Bollo --- include/afb-plugin.h | 1 - include/afb-req-itf.h | 58 +++++++++++++++++++++++++++++---------------- plugins/samples/ClientCtx.c | 42 +++++--------------------------- plugins/session/token-api.c | 19 +++++++-------- src/afb-api-so.c | 15 +----------- src/afb-apis.c | 9 +------ src/afb-apis.h | 2 -- src/afb-hreq.c | 6 +++-- src/afb-ws-json.c | 7 ++++-- src/main.c | 3 ++- src/session.c | 33 ++++++++++++++++---------- src/session.h | 13 ++++++++-- 12 files changed, 97 insertions(+), 111 deletions(-) diff --git a/include/afb-plugin.h b/include/afb-plugin.h index c7252d64..dfb6fbad 100644 --- a/include/afb-plugin.h +++ b/include/afb-plugin.h @@ -55,7 +55,6 @@ struct AFB_plugin const char *info; const char *prefix; const struct AFB_restapi *apis; - void (*freeCtxCB)(void*); // callback to free application context [null for standard free] }; /* config mode */ diff --git a/include/afb-req-itf.h b/include/afb-req-itf.h index 357ffd7b..f03ce868 100644 --- a/include/afb-req-itf.h +++ b/include/afb-req-itf.h @@ -26,26 +26,27 @@ struct afb_arg { }; struct afb_req_itf { - struct json_object *(*json)(void *data); - struct afb_arg (*get)(void *data, const char *name); - void (*success)(void *data, struct json_object *obj, const char *info); - void (*fail)(void *data, const char *status, const char *info); - const char *(*raw)(void *data, size_t *size); - void (*send)(void *data, char *buffer, size_t size); - int (*session_create)(void *data); - int (*session_check)(void *data, int refresh); - void (*session_close)(void *data); + struct json_object *(*json)(void *req_closure); + struct afb_arg (*get)(void *req_closure, const char *name); + void (*success)(void *req_closure, struct json_object *obj, const char *info); + void (*fail)(void *req_closure, const char *status, const char *info); + const char *(*raw)(void *req_closure, size_t *size); + void (*send)(void *req_closure, char *buffer, size_t size); + void *(*context_get)(void *ctx_closure); + void (*context_set)(void *ctx_closure, void *context, void (*free_context)(void*)); + int (*session_create)(void *req_closure); + int (*session_check)(void *req_closure, int refresh); + void (*session_close)(void *req_closure); }; struct afb_req { const struct afb_req_itf *itf; - void *data; - void **context; + void *req_closure; + void *ctx_closure; }; - static inline struct afb_arg afb_req_get(struct afb_req req, const char *name) { - return req.itf->get(req.data, name); + return req.itf->get(req.req_closure, name); } static inline const char *afb_req_value(struct afb_req req, const char *name) @@ -60,32 +61,47 @@ static inline const char *afb_req_path(struct afb_req req, const char *name) static inline struct json_object *afb_req_json(struct afb_req req) { - return req.itf->json(req.data); + return req.itf->json(req.req_closure); } static inline void afb_req_success(struct afb_req req, struct json_object *obj, const char *info) { - req.itf->success(req.data, obj, info); + req.itf->success(req.req_closure, obj, info); } static inline void afb_req_fail(struct afb_req req, const char *status, const char *info) { - req.itf->fail(req.data, status, info); + req.itf->fail(req.req_closure, status, info); } static inline const char *afb_req_raw(struct afb_req req, size_t *size) { - return req.itf->raw(req.data, size); + return req.itf->raw(req.req_closure, size); } static inline void afb_req_send(struct afb_req req, char *buffer, size_t size) { - req.itf->send(req.data, buffer, size); + req.itf->send(req.req_closure, buffer, size); +} + +static inline void *afb_req_context_get(struct afb_req req) +{ + return req.itf->context_get(req.ctx_closure); +} + +static inline void afb_req_context_set(struct afb_req req, void *context, void (*free_context)(void*)) +{ + return req.itf->context_set(req.ctx_closure, context, free_context); +} + +static inline void afb_req_context_clear(struct afb_req req) +{ + afb_req_context_set(req, NULL, NULL); } static inline int afb_req_session_create(struct afb_req req) { - int result = req.itf->session_create(req.data); + int result = req.itf->session_create(req.req_closure); if (!result) afb_req_fail(req, "fail", "Can't create the session"); return result; @@ -93,7 +109,7 @@ static inline int afb_req_session_create(struct afb_req req) static inline int afb_req_session_check(struct afb_req req, int refresh) { - int result = req.itf->session_check(req.data, refresh); + int result = req.itf->session_check(req.req_closure, refresh); if (!result) afb_req_fail(req, "fail", "Token chek failed for the session"); return result; @@ -101,7 +117,7 @@ static inline int afb_req_session_check(struct afb_req req, int refresh) static inline void afb_req_session_close(struct afb_req req) { - req.itf->session_close(req.data); + req.itf->session_close(req.req_closure); } #if !defined(_GNU_SOURCE) diff --git a/plugins/samples/ClientCtx.c b/plugins/samples/ClientCtx.c index 24cb4f30..11d10240 100644 --- a/plugins/samples/ClientCtx.c +++ b/plugins/samples/ClientCtx.c @@ -21,19 +21,6 @@ #include "afb-plugin.h" -typedef struct { - /* - * In case your plugin is implemented on multiple files or used share routines - * with other plugins, it might not be possible to use global static variable. - * In this case you can attach a static handle to your plugin. This handle - * is passed within each API call under request->handle - * - */ - void *anythingYouWant; - - -} MyPluginHandleT; - typedef struct { /* * client context is attached a session but private to a each plugin. @@ -57,24 +44,19 @@ typedef struct { } MyClientContextT; - -// Plugin handle should not be in stack (malloc or static) -static MyPluginHandleT global_handle; - // This function is call at session open time. Any client trying to // call it with an already open session will be denied. // Ex: http://localhost:1234/api/context/create?token=123456789 static void myCreate (struct afb_req request) { MyClientContextT *ctx = malloc (sizeof (MyClientContextT)); - MyPluginHandleT *handle = (MyPluginHandleT*) &global_handle; // store something in our plugin private client context ctx->count = 0; ctx->abcd = "SomeThingUseful"; - *request.context = ctx; - afb_req_success_f(request, NULL, "SUCCESS: create client context for plugin [%s]", handle->anythingYouWant); + afb_req_context_set(request, ctx, free); + afb_req_success_f(request, NULL, "SUCCESS: create client context for plugin [%s]", ctx->abcd); } // This function can only be called with a valid token. Token should be renew before @@ -83,12 +65,11 @@ static void myCreate (struct afb_req request) // ex: http://localhost:1234/api/context/action?token=xxxxxx-xxxxxx-xxxxx-xxxxx-xxxxxx static void myAction (struct afb_req request) { - MyPluginHandleT *handle = (MyPluginHandleT*) &global_handle; - MyClientContextT *ctx = (MyClientContextT*) *request.context; + MyClientContextT *ctx = (MyClientContextT*) afb_req_context_get(request); // store something in our plugin private client context ctx->count++; - afb_req_success_f(request, NULL, "SUCCESS: plugin [%s] Check=[%d]\n", handle->anythingYouWant, ctx->count); + afb_req_success_f(request, NULL, "SUCCESS: plugin [%s] Check=[%d]\n", ctx->abcd, ctx->count); } // After execution of this function, client session will be close and if they @@ -97,20 +78,11 @@ static void myAction (struct afb_req request) // ex: http://localhost:1234/api/context/close?token=xxxxxx-xxxxxx-xxxxx-xxxxx-xxxxxx static void myClose (struct afb_req request) { - MyPluginHandleT *handle = (MyPluginHandleT*) &global_handle; - MyClientContextT *ctx = (MyClientContextT*) *request.context; + MyClientContextT *ctx = (MyClientContextT*) afb_req_context_get(request); // store something in our plugin private client context ctx->count++; - afb_req_success_f(request, NULL, "SUCCESS: plugin [%s] Close=[%d]\n", handle->anythingYouWant, ctx->count); -} - -static void freeCtxCB (MyClientContextT *ctx) { - MyPluginHandleT *handle = (MyPluginHandleT*) &global_handle; - fprintf (stderr, "FreeCtxCB Plugin=[%s] count=[%d]", (char*)handle->anythingYouWant, ctx->count); - free (ctx); - - // Note: handle should be free it is a static resource attached to plugin and not to session + afb_req_success_f(request, NULL, "SUCCESS: plugin [%s] Close=[%d]\n", ctx->abcd, ctx->count); } // NOTE: this sample does not use session to keep test a basic as possible @@ -127,12 +99,10 @@ static const struct AFB_plugin plugin_desc = { .info = "Sample of Client Context Usage", .prefix = "context", .apis = pluginApis, - .freeCtxCB = (void*)freeCtxCB }; const struct AFB_plugin *pluginRegister (const struct AFB_interface *itf) { - global_handle.anythingYouWant = "anythingYouWant"; return &plugin_desc; } diff --git a/plugins/session/token-api.c b/plugins/session/token-api.c index 91f9cd8f..bd76ceef 100644 --- a/plugins/session/token-api.c +++ b/plugins/session/token-api.c @@ -28,13 +28,20 @@ typedef struct { } MyClientApplicationHandle; +// This function is call when Client Session Context is removed +// Note: when freeCtxCB==NULL standard free/malloc is called +static void clientContextFree(void *context) { + fprintf (stderr,"Plugin[token] Closing Session\n"); + free (context); +} + // Request Creation of new context if it does not exist static void clientContextCreate (struct afb_req request) { json_object *jresp; // add an application specific client context to session - request.context = malloc (sizeof (MyClientApplicationHandle)); + afb_req_context_set(request, malloc (sizeof (MyClientApplicationHandle)), clientContextFree); // Send response to UI jresp = json_object_new_object(); @@ -92,13 +99,6 @@ static void clientGetPing (struct afb_req request) { } -// This function is call when Client Session Context is removed -// Note: when freeCtxCB==NULL standard free/malloc is called -static void clientContextFree(void *context) { - fprintf (stderr,"Plugin[token] Closing Session\n"); - free (context); -} - static const struct AFB_restapi pluginApis[]= { {"ping" , AFB_SESSION_NONE , clientGetPing ,"Ping Rest Test Service"}, {"create" , AFB_SESSION_CREATE, clientContextCreate ,"Request Client Context Creation"}, @@ -112,8 +112,7 @@ static const struct AFB_plugin plugin_desc = { .type = AFB_PLUGIN_JSON, .info = "Application Framework Binder Service", .prefix = "token", - .apis = pluginApis, - .freeCtxCB = clientContextFree + .apis = pluginApis }; const struct AFB_plugin *pluginRegister (const struct AFB_interface *itf) diff --git a/src/afb-api-so.c b/src/afb-api-so.c index 60af72ef..c3cb08d7 100644 --- a/src/afb-api-so.c +++ b/src/afb-api-so.c @@ -86,17 +86,6 @@ static const struct afb_daemon_itf daemon_itf = { .get_pollmgr = (void*)afb_api_so_get_pollmgr }; -static void free_context(struct api_so_desc *desc, void *context) -{ - void (*cb)(void*); - - cb = desc->plugin->freeCtxCB; - if (cb) - cb(context); - else - free(context); -} - static void trapping_call(struct afb_req req, void(*cb)(struct afb_req)) { volatile int signum, timerset; @@ -159,7 +148,6 @@ static void call_check(struct afb_req req, const struct AFB_restapi *verb) break; } trapping_call(req, verb->callback); - if (verb->session == AFB_SESSION_CLOSE) afb_req_session_close(req); } @@ -238,8 +226,7 @@ int afb_api_so_add_plugin(const char *path) /* records the plugin */ if (afb_apis_add(desc->plugin->prefix, (struct afb_api){ .closure = desc, - .call = (void*)call, - .free_context = (void*)free_context}) < 0) { + .call = (void*)call}) < 0) { fprintf(stderr, "ERROR: plugin [%s] can't be registered...\n", path); goto error3; } diff --git a/src/afb-apis.c b/src/afb-apis.c index 0af3b42c..2822575b 100644 --- a/src/afb-apis.c +++ b/src/afb-apis.c @@ -41,13 +41,6 @@ int afb_apis_count() return apis_count; } -void afb_apis_free_context(int apiidx, void *context) -{ - const struct afb_api *api; - api = &apis_array[apiidx].api; - api->free_context(api->closure, context); -} - int afb_apis_add(const char *name, struct afb_api api) { struct api_desc *apis; @@ -98,7 +91,7 @@ void afb_apis_call(struct afb_req req, struct AFB_clientCtx *context, const char a = apis_array; for (i = 0 ; i < apis_count ; i++, a++) { if (a->namelen == lenapi && !strncasecmp(a->name, api, lenapi)) { - req.context = &context->contexts[i]; + req.ctx_closure = &context->contexts[i]; a->api.call(a->api.closure, req, verb, lenverb); return; } diff --git a/src/afb-apis.h b/src/afb-apis.h index 59c7008f..985923f5 100644 --- a/src/afb-apis.h +++ b/src/afb-apis.h @@ -24,7 +24,6 @@ struct afb_api { void *closure; void (*call)(void *closure, struct afb_req req, const char *verb, size_t lenverb); - void (*free_context)(void *closure, void *context); }; @@ -32,5 +31,4 @@ extern int afb_apis_count(); extern int afb_apis_add(const char *name, struct afb_api api); extern void afb_apis_call(struct afb_req req, struct AFB_clientCtx *context, const char *api, size_t lenapi, const char *verb, size_t lenverb); -extern void afb_apis_free_context(int apiidx, void *context); diff --git a/src/afb-hreq.c b/src/afb-hreq.c index 93cce62b..72b90504 100644 --- a/src/afb-hreq.c +++ b/src/afb-hreq.c @@ -81,7 +81,9 @@ static const struct afb_req_itf afb_hreq_itf = { .send = (void*)req_send, .session_create = (void*)req_session_create, .session_check = (void*)req_session_check, - .session_close = (void*)req_session_close + .session_close = (void*)req_session_close, + .context_get = (void*)afb_context_get, + .context_set = (void*)afb_context_set }; static struct hreq_data *get_data(struct afb_hreq *hreq, const char *key, int create) @@ -584,7 +586,7 @@ int afb_hreq_post_add_file(struct afb_hreq *hreq, const char *key, const char *f struct afb_req afb_hreq_to_req(struct afb_hreq *hreq) { - return (struct afb_req){ .itf = &afb_hreq_itf, .data = hreq }; + return (struct afb_req){ .itf = &afb_hreq_itf, .req_closure = hreq }; } static struct afb_arg req_get(struct afb_hreq *hreq, const char *name) diff --git a/src/afb-ws-json.c b/src/afb-ws-json.c index a1766888..a34142c9 100644 --- a/src/afb-ws-json.c +++ b/src/afb-ws-json.c @@ -141,7 +141,10 @@ static const struct afb_req_itf wsreq_itf = { .send = (void*)wsreq_send, .session_create = (void*)wsreq_session_create, .session_check = (void*)wsreq_session_check, - .session_close = (void*)wsreq_session_close + .session_close = (void*)wsreq_session_close, + .context_get = (void*)afb_context_get, + .context_set = (void*)afb_context_set + }; static int aws_wsreq_parse(struct afb_wsreq *r, char *text, size_t size) @@ -297,7 +300,7 @@ static void aws_on_text(struct afb_ws_json *ws, char *text, size_t size) wsreq->next = ws->requests; ws->requests = wsreq; - r.data = wsreq; + r.req_closure = wsreq; r.itf = &wsreq_itf; afb_apis_call(r, ws->context, wsreq->api, wsreq->apilen, wsreq->verb, wsreq->verblen); return; diff --git a/src/main.c b/src/main.c index e899739c..8ec684fe 100644 --- a/src/main.c +++ b/src/main.c @@ -34,6 +34,7 @@ #include "afb-config.h" #include "afb-hswitch.h" +#include "afb-apis.h" #include "afb-api-so.h" #include "afb-hsrv.h" #include "afb-hreq.h" @@ -577,7 +578,7 @@ int main(int argc, char *argv[]) { if (config->ldpaths) afb_api_so_add_pathset(config->ldpaths); - ctxStoreInit(CTX_NBCLIENTS, config->cntxTimeout, config->token); + ctxStoreInit(CTX_NBCLIENTS, config->cntxTimeout, config->token, afb_apis_count()); if (!afb_hreq_init_cookie(config->httpdPort, config->rootapi, DEFLT_CNTX_TIMEOUT)) { fprintf (stderr, "ERR: initialisation of cookies failed\n"); exit (1); diff --git a/src/session.c b/src/session.c index 329e17ab..fbc7f2fb 100644 --- a/src/session.c +++ b/src/session.c @@ -24,7 +24,6 @@ #include #include -#include "afb-apis.h" #include "session.h" #define NOW (time(NULL)) @@ -40,6 +39,20 @@ static struct { const char *initok; } sessions; +void *afb_context_get(struct afb_context *actx) +{ + return actx->context; +} + +void afb_context_set(struct afb_context *actx, void *context, void (*free_context)(void*)) +{ +fprintf(stderr, "afb_context_set(%p,%p) was (%p,%p)\n",context, free_context, actx->context, actx->free_context); + if (actx->context != NULL && actx->free_context != NULL) + actx->free_context(actx->context); + actx->context = context; + actx->free_context = free_context; +} + // Free context [XXXX Should be protected again memory abort XXXX] static void ctxUuidFreeCB (struct AFB_clientCtx *client) { @@ -49,22 +62,18 @@ static void ctxUuidFreeCB (struct AFB_clientCtx *client) 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]); - client->contexts[idx] = NULL; - } - } + for (idx=0; idx < sessions.apicount; idx ++) + afb_context_set(&client->contexts[idx], NULL, NULL); } // Create a new store in RAM, not that is too small it will be automatically extended -void ctxStoreInit (int nbSession, int timeout, const char *initok) +void ctxStoreInit (int max_session_count, int timeout, const char *initok, int context_count) { // let's create as store as hashtable does not have any - sessions.store = calloc (1 + (unsigned)nbSession, sizeof(struct AFB_clientCtx)); - sessions.max = nbSession; + sessions.store = calloc (1 + (unsigned)max_session_count, sizeof(struct AFB_clientCtx)); + sessions.max = max_session_count; sessions.timeout = timeout; - sessions.apicount = afb_apis_count(); + sessions.apicount = context_count; if (strlen(initok) >= 37) { fprintf(stderr, "Error: initial token '%s' too long (max length 36)", initok); exit(1); @@ -191,7 +200,7 @@ TODO remove? not remove? /* returns a new one */ clientCtx = calloc(1, sizeof(struct AFB_clientCtx)); // init NULL clientContext if (clientCtx != NULL) { - clientCtx->contexts = calloc ((unsigned)sessions.apicount, sizeof (void*)); + clientCtx->contexts = calloc ((unsigned)sessions.apicount, sizeof(*clientCtx->contexts)); if (clientCtx->contexts != NULL) { /* generate the uuid */ if (uuid == NULL) { diff --git a/src/session.h b/src/session.h index 0a61612d..569af654 100644 --- a/src/session.h +++ b/src/session.h @@ -18,17 +18,26 @@ #pragma once +struct afb_context +{ + void *context; + void (*free_context)(void*); +}; + +extern void *afb_context_get(struct afb_context *actx); +extern void afb_context_set(struct afb_context *actx, void *context, void (*free_context)(void*)); + struct AFB_clientCtx { time_t expiration; // expiration time of the token int created; unsigned refcount; - void **contexts; // application specific context [one per plugin] + struct afb_context *contexts; char uuid[37]; // long term authentication of remote client char token[37]; // short term authentication of remote client }; -extern void ctxStoreInit (int nbSession, int timeout, const char *initok); +extern void ctxStoreInit (int max_session_count, int timeout, const char *initok, int context_count); extern struct AFB_clientCtx *ctxClientGetForUuid (const char *uuid); extern struct AFB_clientCtx *ctxClientGet(struct AFB_clientCtx *clientCtx); -- 2.16.6