diff options
author | José Bollo <jose.bollo@iot.bzh> | 2016-04-04 17:48:50 +0200 |
---|---|---|
committer | José Bollo <jose.bollo@iot.bzh> | 2016-04-04 17:48:50 +0200 |
commit | 11d36a9f7e16aa9992835f8ce06f0e1e5297b131 (patch) | |
tree | ff15e8fe346df9bcc92e063747c43476054113f7 /src | |
parent | b8d4c81cc8175ce49c77d41e572a9f1a2e367cdc (diff) |
work in progress, session handling
Change-Id: I0393346280825e24a34e8db386160d857723b841
Signed-off-by: José Bollo <jose.bollo@iot.bzh>
Diffstat (limited to 'src')
-rw-r--r-- | src/afb-apis.c | 112 | ||||
-rw-r--r-- | src/afb-apis.h | 9 | ||||
-rw-r--r-- | src/afb-hreq.c | 115 | ||||
-rw-r--r-- | src/afb-hreq.h | 6 | ||||
-rw-r--r-- | src/http-svc.c | 34 | ||||
-rw-r--r-- | src/local-def.h | 55 | ||||
-rw-r--r-- | src/main.c | 5 | ||||
-rw-r--r-- | src/session.c | 132 | ||||
-rw-r--r-- | src/session.h | 22 |
9 files changed, 233 insertions, 257 deletions
diff --git a/src/afb-apis.c b/src/afb-apis.c index 0a04ed73..735649ca 100644 --- a/src/afb-apis.c +++ b/src/afb-apis.c @@ -41,13 +41,15 @@ #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; } } diff --git a/src/afb-apis.h b/src/afb-apis.h index dc4401cf..9127e6d8 100644 --- a/src/afb-apis.h +++ b/src/afb-apis.h @@ -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); diff --git a/src/afb-hreq.c b/src/afb-hreq.c index e146bcb4..16c235ab 100644 --- a/src/afb-hreq.c +++ b/src/afb-hreq.c @@ -31,11 +31,21 @@ #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); +} + + + diff --git a/src/afb-hreq.h b/src/afb-hreq.h index fb914f13..cf236380 100644 --- a/src/afb-hreq.h +++ b/src/afb-hreq.h @@ -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); diff --git a/src/http-svc.c b/src/http-svc.c index 9235bf87..c767de71 100644 --- a/src/http-svc.c +++ b/src/http-svc.c @@ -31,12 +31,12 @@ #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) diff --git a/src/local-def.h b/src/local-def.h index a1cac538..39ae3181 100644 --- a/src/local-def.h +++ b/src/local-def.h @@ -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,... }; @@ -27,10 +27,7 @@ #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" diff --git a/src/session.c b/src/session.c index ad411239..e9cf298e 100644 --- a/src/session.c +++ b/src/session.c @@ -29,16 +29,6 @@ #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; } diff --git a/src/session.h b/src/session.h index 9b54179b..28f25991 100644 --- a/src/session.h +++ b/src/session.h @@ -18,19 +18,19 @@ 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); |