Improves naming of session's module
authorJosé Bollo <jose.bollo@iot.bzh>
Tue, 3 Jan 2017 16:52:19 +0000 (17:52 +0100)
committerJosé Bollo <jose.bollo@iot.bzh>
Tue, 3 Jan 2017 17:23:22 +0000 (18:23 +0100)
Make names looking like other names

Change-Id: I63ce3d8a3d84193eca9d517cecb1888d630a9b2d
Signed-off-by: José Bollo <jose.bollo@iot.bzh>
21 files changed:
src/CMakeLists.txt
src/afb-api-dbus.c
src/afb-api-so.c
src/afb-api-ws.c
src/afb-apis.c
src/afb-config.h
src/afb-context.c
src/afb-context.h
src/afb-evt.h
src/afb-hook.c
src/afb-hook.h
src/afb-hreq.c
src/afb-hreq.h
src/afb-hswitch.c
src/afb-session.c [new file with mode: 0644]
src/afb-session.h [new file with mode: 0644]
src/afb-svc.c
src/afb-ws-json1.c
src/main.c
src/session.c [deleted file]
src/session.h [deleted file]

index 80d09bf..0fcfba6 100644 (file)
@@ -64,6 +64,7 @@ ADD_LIBRARY(afb-lib STATIC
        afb-hswitch.c
        afb-method.c
        afb-msg-json.c
+       afb-session.c
        afb-sig-handler.c
        afb-svc.c
        afb-subcall.c
@@ -74,7 +75,6 @@ ADD_LIBRARY(afb-lib STATIC
        afb-ws.c
        afb-wsj1.c
        locale-root.c
-       session.c
        verbose.c
        websock.c
 )
index 9ebe1fa..4a5a4f1 100644 (file)
@@ -30,7 +30,7 @@
 
 #include "afb-common.h"
 
-#include "session.h"
+#include "afb-session.h"
 #include "afb-msg-json.h"
 #include "afb-apis.h"
 #include "afb-api-so.h"
@@ -340,7 +340,7 @@ static void api_dbus_client_call(struct api_dbus *api, struct afb_req req, struc
 
        rc = sd_bus_message_append(msg, "ssu",
                        afb_req_raw(req, &size),
-                       ctxClientGetUuid(context->session),
+                       afb_session_uuid(context->session),
                        (uint32_t)context->flags);
        if (rc < 0)
                goto error;
@@ -724,7 +724,7 @@ static void afb_api_dbus_server_listener_free(struct listener *listener)
        free(listener);
 }
 
-static struct listener *afb_api_dbus_server_listerner_get(struct api_dbus *api, const char *sender, struct AFB_clientCtx *session)
+static struct listener *afb_api_dbus_server_listerner_get(struct api_dbus *api, const char *sender, struct afb_session *session)
 {
        int rc;
        struct listener *listener;
@@ -736,7 +736,7 @@ static struct listener *afb_api_dbus_server_listerner_get(struct api_dbus *api,
                return NULL;
 
        /* retrieves the stored listener */
-       listener = ctxClientCookieGet(session, destination);
+       listener = afb_session_get_cookie(session, destination);
        if (listener != NULL) {
                /* found */
                afb_api_dbus_server_destination_unref(destination);
@@ -751,7 +751,7 @@ static struct listener *afb_api_dbus_server_listerner_get(struct api_dbus *api,
                listener->destination = destination;
                listener->listener = afb_evt_listener_create(&evt_push_itf, destination);
                if (listener->listener != NULL) {
-                       rc = ctxClientCookieSet(session, destination, listener, (void*)afb_api_dbus_server_listener_free);
+                       rc = afb_session_set_cookie(session, destination, listener, (void*)afb_api_dbus_server_listener_free);
                        if (rc == 0)
                                return listener;
                        afb_evt_listener_unref(listener->listener);
@@ -963,7 +963,7 @@ static int api_dbus_server_on_object_called(sd_bus_message *message, void *userd
        struct api_dbus *api = userdata;
        struct afb_req areq;
        uint32_t flags;
-       struct AFB_clientCtx *session;
+       struct afb_session *session;
        struct listener *listener;
 
        /* check the interface */
index 554df39..74f94f3 100644 (file)
@@ -33,7 +33,7 @@
 #include <afb/afb-req-itf.h>
 #include <afb/afb-event-itf.h>
 
-#include "session.h"
+#include "afb-session.h"
 #include "afb-common.h"
 #include "afb-context.h"
 #include "afb-apis.h"
index cb7b4f5..4d1f08c 100644 (file)
@@ -37,7 +37,7 @@
 
 #include "afb-common.h"
 
-#include "session.h"
+#include "afb-session.h"
 #include "afb-ws.h"
 #include "afb-msg-json.h"
 #include "afb-apis.h"
@@ -827,7 +827,7 @@ static void api_ws_client_call_cb(void * closure, struct afb_req req, struct afb
        if (!api_ws_write_uint32(&wb, memo->msgid)
         || !api_ws_write_uint32(&wb, (uint32_t)context->flags)
         || !api_ws_write_string_nz(&wb, verb, lenverb)
-        || !api_ws_write_string(&wb, ctxClientGetUuid(context->session))
+        || !api_ws_write_string(&wb, afb_session_uuid(context->session))
         || !api_ws_write_string_length(&wb, raw, szraw))
                goto overflow;
 
index 6bc4277..7db3e75 100644 (file)
@@ -22,7 +22,7 @@
 #include <stdio.h>
 #include <string.h>
 
-#include "session.h"
+#include "afb-session.h"
 #include "verbose.h"
 #include "afb-apis.h"
 #include "afb-context.h"
index 9ff4cd6..7bbad4d 100644 (file)
@@ -13,8 +13,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#ifndef LOCAL_DEF_H
-#define LOCAL_DEF_H
 
 #pragma once
 
@@ -66,4 +64,3 @@ struct afb_config
        } aliasdir[MAX_ALIAS];  // alias mapping for icons,apps,...
 };
 
-#endif /* LOCAL_DEF_H */
index 0bcc79c..eec4ebb 100644 (file)
 #include <assert.h>
 #include <stdlib.h>
 
-#include "session.h"
+#include "afb-session.h"
 #include "afb-context.h"
 
-static void init_context(struct afb_context *context, struct AFB_clientCtx *session, const char *token)
+static void init_context(struct afb_context *context, struct afb_session *session, const char *token)
 {
        assert(session != NULL);
 
@@ -32,28 +32,28 @@ static void init_context(struct afb_context *context, struct AFB_clientCtx *sess
        context->session = session;
        context->flags = 0;
        context->api_index = -1;
-       context->loa_in = ctxClientGetLOA(session) & 7;
+       context->loa_in = afb_session_get_LOA(session) & 7;
 
        /* check the token */
        if (token != NULL) {
-               if (ctxTokenCheck(session, token))
+               if (afb_session_check_token(session, token))
                        context->validated = 1;
                else
                        context->invalidated = 1;
        }
 }
 
-void afb_context_init(struct afb_context *context, struct AFB_clientCtx *session, const char *token)
+void afb_context_init(struct afb_context *context, struct afb_session *session, const char *token)
 {
-       init_context(context, ctxClientAddRef(session), token);
+       init_context(context, afb_session_addref(session), token);
 }
 
 int afb_context_connect(struct afb_context *context, const char *uuid, const char *token)
 {
        int created;
-       struct AFB_clientCtx *session;
+       struct afb_session *session;
 
-       session = ctxClientGetSession (uuid, &created);
+       session = afb_session_get (uuid, &created);
        if (session == NULL)
                return -1;
        init_context(context, session, token);
@@ -68,18 +68,18 @@ void afb_context_disconnect(struct afb_context *context)
 {
        if (context->session != NULL) {
                if (context->refreshing && !context->refreshed) {
-                       ctxTokenNew (context->session);
+                       afb_session_new_token (context->session);
                        context->refreshed = 1;
                }
                if (context->loa_changing && !context->loa_changed) {
-                       ctxClientSetLOA (context->session, context->loa_out);
+                       afb_session_set_LOA (context->session, context->loa_out);
                        context->loa_changed = 1;
                }
                if (context->closing && !context->closed) {
-                       ctxClientClose(context->session);
+                       afb_session_close(context->session);
                        context->closed = 1;
                }
-               ctxClientUnref(context->session);
+               afb_session_unref(context->session);
                context->session = NULL;
        }
 }
@@ -91,10 +91,10 @@ const char *afb_context_sent_token(struct afb_context *context)
        if (!context->refreshing)
                return NULL;
        if (!context->refreshed) {
-               ctxTokenNew (context->session);
+               afb_session_new_token (context->session);
                context->refreshed = 1;
        }
-       return ctxClientGetToken(context->session);
+       return afb_session_token(context->session);
 }
 
 const char *afb_context_sent_uuid(struct afb_context *context)
@@ -103,19 +103,19 @@ const char *afb_context_sent_uuid(struct afb_context *context)
                return NULL;
        if (!context->created)
                return NULL;
-       return ctxClientGetUuid(context->session);
+       return afb_session_uuid(context->session);
 }
 
 void *afb_context_get(struct afb_context *context)
 {
        assert(context->session != NULL);
-       return ctxClientValueGet(context->session, context->api_index);
+       return afb_session_get_value(context->session, context->api_index);
 }
 
 void afb_context_set(struct afb_context *context, void *value, void (*free_value)(void*))
 {
        assert(context->session != NULL);
-       return ctxClientValueSet(context->session, context->api_index, value, free_value);
+       return afb_session_set_value(context->session, context->api_index, value, free_value);
 }
 
 void afb_context_close(struct afb_context *context)
index 35709e2..d65e6ff 100644 (file)
 
 #pragma once
 
-struct AFB_clientCtx;
+struct afb_session;
 
 struct afb_context
 {
-       struct AFB_clientCtx *session;
+       struct afb_session *session;
        union {
                unsigned flags;
                struct {
@@ -41,7 +41,7 @@ struct afb_context
        int api_index;
 };
 
-extern void afb_context_init(struct afb_context *context, struct AFB_clientCtx *session, const char *token);
+extern void afb_context_init(struct afb_context *context, struct afb_session *session, const char *token);
 extern int afb_context_connect(struct afb_context *context, const char *uuid, const char *token);
 extern void afb_context_disconnect(struct afb_context *context);
 extern const char *afb_context_sent_token(struct afb_context *context);
index bd765b8..52b40ab 100644 (file)
@@ -18,7 +18,7 @@
 #pragma once
 
 struct afb_event;
-struct AFB_clientCtx;
+struct afb_session;
 
 struct afb_evt_listener;
 
index f7d3e5b..d5c534d 100644 (file)
@@ -28,7 +28,7 @@
 
 #include "afb-context.h"
 #include "afb-hook.h"
-#include "session.h"
+#include "afb-session.h"
 #include "verbose.h"
 
 /*
@@ -39,7 +39,7 @@ struct afb_hook {
        unsigned refcount; /* reference count */
        char *api; /* api hooked or NULL for any */
        char *verb; /* verb hooked or NULL for any */
-       struct AFB_clientCtx *session; /* session hooked or NULL if any */
+       struct afb_session *session; /* session hooked or NULL if any */
        unsigned flags; /* hook flags */
        struct afb_hook_req_itf *reqitf; /* interface of hook */
        void *closure; /* closure for callbacks */
@@ -526,7 +526,7 @@ struct afb_req afb_hook_req_call(struct afb_req req, struct afb_context *context
        return req;
 }
 
-struct afb_hook *afb_hook_req_create(const char *api, const char *verb, struct AFB_clientCtx *session, unsigned flags, struct afb_hook_req_itf *itf, void *closure)
+struct afb_hook *afb_hook_req_create(const char *api, const char *verb, struct afb_session *session, unsigned flags, struct afb_hook_req_itf *itf, void *closure)
 {
        struct afb_hook *hook;
 
@@ -536,13 +536,13 @@ struct afb_hook *afb_hook_req_create(const char *api, const char *verb, struct A
 
        hook->api = api ? strdup(api) : NULL;
        hook->verb = verb ? strdup(verb) : NULL;
-       hook->session = session ? ctxClientAddRef(session) : NULL;
+       hook->session = session ? afb_session_addref(session) : NULL;
 
        if ((api && !hook->api) || (verb && !hook->verb)) {
                free(hook->api);
                free(hook->verb);
                if (hook->session)
-                       ctxClientUnref(hook->session);
+                       afb_session_unref(hook->session);
                free(hook);
                return NULL;
        }
@@ -577,7 +577,7 @@ void afb_hook_unref(struct afb_hook *hook)
                free(hook->api);
                free(hook->verb);
                if (hook->session)
-                       ctxClientUnref(hook->session);
+                       afb_session_unref(hook->session);
                free(hook);
        }
 }
index ae6ef83..2ad01b8 100644 (file)
@@ -59,7 +59,7 @@ struct afb_context;
 struct json_object;
 struct afb_arg;
 struct afb_event;
-struct AFB_clientCtx;
+struct afb_session;
 
 struct afb_hook;
 struct afb_hook_req;
@@ -90,7 +90,7 @@ struct afb_hook_req_itf {
 
 extern struct afb_req afb_hook_req_call(struct afb_req req, struct afb_context *context, const char *api, size_t lenapi, const char *verb, size_t lenverb);
 
-extern struct afb_hook *afb_hook_req_create(const char *api, const char *verb, struct AFB_clientCtx *session, unsigned flags, struct afb_hook_req_itf *itf, void *closure);
+extern struct afb_hook *afb_hook_req_create(const char *api, const char *verb, struct afb_session *session, unsigned flags, struct afb_hook_req_itf *itf, void *closure);
 extern struct afb_hook *afb_hook_addref(struct afb_hook *spec);
 extern void afb_hook_unref(struct afb_hook *spec);
 
index b0f1172..b218045 100644 (file)
@@ -38,7 +38,7 @@
 #include "afb-context.h"
 #include "afb-hreq.h"
 #include "afb-subcall.h"
-#include "session.h"
+#include "afb-session.h"
 #include "verbose.h"
 #include "locale-root.h"
 
index 72cefcf..f07f2fa 100644 (file)
@@ -17,7 +17,7 @@
 
 #pragma once
 
-struct AFB_clientCtx;
+struct afb_session;
 struct json_object;
 struct hreq_data;
 struct afb_hsrv;
index 90dc2ff..9c929e8 100644 (file)
@@ -27,7 +27,7 @@
 #include "afb-context.h"
 #include "afb-hreq.h"
 #include "afb-apis.h"
-#include "session.h"
+#include "afb-session.h"
 #include "afb-websock.h"
 
 int afb_hswitch_apis(struct afb_hreq *hreq, void *data)
diff --git a/src/afb-session.c b/src/afb-session.c
new file mode 100644 (file)
index 0000000..db81457
--- /dev/null
@@ -0,0 +1,461 @@
+/*
+ * Copyright (C) 2015, 2016, 2017 "IoT.bzh"
+ * Author "Fulup Ar Foll"
+ * Author: José Bollo <jose.bollo@iot.bzh>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <time.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <string.h>
+#include <uuid/uuid.h>
+#include <assert.h>
+#include <errno.h>
+
+#include <json-c/json.h>
+
+#include "afb-session.h"
+#include "verbose.h"
+
+#define NOW (time(NULL))
+
+struct value
+{
+       void *value;
+       void (*freecb)(void*);
+};
+
+struct cookie
+{
+       struct cookie *next;
+       const void *key;
+       void *value;
+       void (*freecb)(void*);
+};
+
+struct afb_session
+{
+       unsigned refcount;
+       unsigned loa;
+       int timeout;
+       time_t expiration;    // expiration time of the token
+       time_t access;
+       char uuid[37];        // long term authentication of remote client
+       char token[37];       // short term authentication of remote client
+       struct value *values;
+       struct cookie *cookies;
+};
+
+// 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
+       struct afb_session **store;          // sessions store
+       int count;                      // current number of sessions
+       int max;
+       int timeout;
+       int apicount;
+       char initok[37];
+} sessions;
+
+/* generate a uuid */
+static void new_uuid(char uuid[37])
+{
+       uuid_t newuuid;
+       uuid_generate(newuuid);
+       uuid_unparse_lower(newuuid, uuid);
+}
+
+// Free context [XXXX Should be protected again memory abort XXXX]
+static void free_data (struct afb_session *session)
+{
+       int idx;
+       struct cookie *cookie;
+
+       // If application add a handle let's free it now
+       assert (session->values != NULL);
+
+       // Free session handle with a standard Free function, with app callback or ignore it
+       for (idx=0; idx < sessions.apicount; idx ++)
+               afb_session_set_value(session, idx, NULL, NULL);
+
+       // free cookies
+       cookie = session->cookies;
+       while (cookie != NULL) {
+               session->cookies = cookie->next;
+               if (cookie->value != NULL && cookie->freecb != NULL)
+                       cookie->freecb(cookie->value);
+               free(cookie);
+               cookie = session->cookies;
+       }
+}
+
+// Create a new store in RAM, not that is too small it will be automatically extended
+void afb_session_init (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)max_session_count, sizeof(struct afb_session));
+       sessions.max = max_session_count;
+       sessions.timeout = timeout;
+       sessions.apicount = context_count;
+       if (initok == NULL)
+               /* without token, a secret is made to forbid creation of sessions */
+               new_uuid(sessions.initok);
+       else if (strlen(initok) < sizeof(sessions.store[0]->token))
+               strcpy(sessions.initok, initok);
+       else {
+               ERROR("initial token '%s' too long (max length 36)", initok);
+               exit(1);
+       }
+}
+
+static struct afb_session *search (const char* uuid)
+{
+       int  idx;
+       struct afb_session *session;
+
+       assert (uuid != NULL);
+
+       pthread_mutex_lock(&sessions.mutex);
+
+       for (idx=0; idx < sessions.max; idx++) {
+               session = sessions.store[idx];
+               if (session && (0 == strcmp (uuid, session->uuid)))
+                       goto found;
+       }
+       session = NULL;
+
+found:
+       pthread_mutex_unlock(&sessions.mutex);
+       return session;
+}
+
+static int destroy (struct afb_session *session)
+{
+       int idx;
+       int status;
+
+       assert (session != NULL);
+
+       pthread_mutex_lock(&sessions.mutex);
+
+       for (idx=0; idx < sessions.max; idx++) {
+               if (sessions.store[idx] == session) {
+                       sessions.store[idx] = NULL;
+                       sessions.count--;
+                       status = 1;
+                       goto deleted;
+               }
+       }
+       status = 0;
+deleted:
+       pthread_mutex_unlock(&sessions.mutex);
+       return status;
+}
+
+static int add (struct afb_session *session)
+{
+       int idx;
+       int status;
+
+       assert (session != NULL);
+
+       pthread_mutex_lock(&sessions.mutex);
+
+       for (idx=0; idx < sessions.max; idx++) {
+               if (NULL == sessions.store[idx]) {
+                       sessions.store[idx] = session;
+                       sessions.count++;
+                       status = 1;
+                       goto added;
+               }
+       }
+       status = 0;
+added:
+       pthread_mutex_unlock(&sessions.mutex);
+       return status;
+}
+
+// Check if context timeout or not
+static int is_expired (struct afb_session *ctx, time_t now)
+{
+       assert (ctx != NULL);
+       return ctx->expiration < now;
+}
+
+// Check if context is active or not
+static int is_active (struct afb_session *ctx, time_t now)
+{
+       assert (ctx != NULL);
+       return ctx->uuid[0] != 0 && ctx->expiration >= now;
+}
+
+// Loop on every entry and remove old context sessions.hash
+static void cleanup (time_t now)
+{
+       struct afb_session *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 && is_expired(ctx, now)) {
+                       afb_session_close (ctx);
+               }
+       }
+}
+
+static struct afb_session *make_session (const char *uuid, int timeout, time_t now)
+{
+       struct afb_session *session;
+
+       /* allocates a new one */
+       session = calloc(1, sizeof(struct afb_session) + ((unsigned)sessions.apicount * sizeof(*session->values)));
+       if (session == NULL) {
+               errno = ENOMEM;
+               goto error;
+       }
+       session->values = (void*)(session + 1);
+
+       /* generate the uuid */
+       if (uuid == NULL) {
+               new_uuid(session->uuid);
+       } else {
+               if (strlen(uuid) >= sizeof session->uuid) {
+                       errno = EINVAL;
+                       goto error2;
+               }
+               strcpy(session->uuid, uuid);
+       }
+
+       /* init the token */
+       strcpy(session->token, sessions.initok);
+       session->timeout = timeout;
+       if (timeout != 0)
+               session->expiration = now + timeout;
+       else {
+               session->expiration = (time_t)(~(time_t)0);
+               if (session->expiration < 0)
+                       session->expiration = (time_t)(((unsigned long long)session->expiration) >> 1);
+       }
+       if (!add (session)) {
+               errno = ENOMEM;
+               goto error2;
+       }
+
+       session->access = now;
+       session->refcount = 1;
+       return session;
+
+error2:
+       free(session);
+error:
+       return NULL;
+}
+
+struct afb_session *afb_session_create (const char *uuid, int timeout)
+{
+       time_t now;
+
+       /* cleaning */
+       now = NOW;
+       cleanup (now);
+
+       /* search for an existing one not too old */
+       if (uuid != NULL && search(uuid) != NULL) {
+               errno = EEXIST;
+               return NULL;
+       }
+
+       return make_session(uuid, timeout, now);
+}
+
+// This function will return exiting session or newly created session
+struct afb_session *afb_session_get (const char *uuid, int *created)
+{
+       struct afb_session *session;
+       time_t now;
+
+       /* cleaning */
+       now = NOW;
+       cleanup (now);
+
+       /* search for an existing one not too old */
+       if (uuid != NULL) {
+               session = search(uuid);
+               if (session != NULL) {
+                       *created = 0;
+                       session->access = now;
+                       session->refcount++;
+                       return session;
+               }
+       }
+
+       *created = 1;
+       return make_session(uuid, sessions.timeout, now);
+}
+
+struct afb_session *afb_session_addref(struct afb_session *session)
+{
+       if (session != NULL)
+               session->refcount++;
+       return session;
+}
+
+void afb_session_unref(struct afb_session *session)
+{
+       if (session != NULL) {
+               assert(session->refcount != 0);
+               --session->refcount;
+               if (session->refcount == 0 && session->uuid[0] == 0) {
+                       destroy (session);
+                       free(session);
+               }
+       }
+}
+
+// Free Client Session Context
+void afb_session_close (struct afb_session *session)
+{
+       assert(session != NULL);
+       if (session->uuid[0] != 0) {
+               session->uuid[0] = 0;
+               free_data (session);
+               if (session->refcount == 0) {
+                       destroy (session);
+                       free(session);
+               }
+       }
+}
+
+// Sample Generic Ping Debug API
+int afb_session_check_token (struct afb_session *session, const char *token)
+{
+       assert(session != NULL);
+       assert(token != NULL);
+
+       // compare current token with previous one
+       if (!is_active (session, NOW))
+               return 0;
+
+       if (session->token[0] && strcmp (token, session->token) != 0)
+               return 0;
+
+       return 1;
+}
+
+// generate a new token and update client context
+void afb_session_new_token (struct afb_session *session)
+{
+       assert(session != NULL);
+
+       // Old token was valid let's regenerate a new one
+       new_uuid(session->token);
+
+       // keep track of time for session timeout and further clean up
+       if (session->timeout != 0)
+               session->expiration = NOW + session->timeout;
+}
+
+const char *afb_session_uuid (struct afb_session *session)
+{
+       assert(session != NULL);
+       return session->uuid;
+}
+
+const char *afb_session_token (struct afb_session *session)
+{
+       assert(session != NULL);
+       return session->token;
+}
+
+unsigned afb_session_get_LOA (struct afb_session *session)
+{
+       assert(session != NULL);
+       return session->loa;
+}
+
+void afb_session_set_LOA (struct afb_session *session, unsigned loa)
+{
+       assert(session != NULL);
+       session->loa = loa;
+}
+
+void *afb_session_get_value(struct afb_session *session, int index)
+{
+       assert(session != NULL);
+       assert(index >= 0);
+       assert(index < sessions.apicount);
+       return session->values[index].value;
+}
+
+void afb_session_set_value(struct afb_session *session, int index, void *value, void (*freecb)(void*))
+{
+       struct value prev;
+       assert(session != NULL);
+       assert(index >= 0);
+       assert(index < sessions.apicount);
+       prev = session->values[index];
+       session->values[index] = (struct value){.value = value, .freecb = freecb};
+       if (prev.value != NULL && prev.value != value && prev.freecb != NULL)
+               prev.freecb(prev.value);
+}
+
+void *afb_session_get_cookie(struct afb_session *session, const void *key)
+{
+       struct cookie *cookie;
+
+       cookie = session->cookies;
+       while(cookie != NULL) {
+               if (cookie->key == key)
+                       return cookie->value;
+               cookie = cookie->next;
+       }
+       return NULL;
+}
+
+int afb_session_set_cookie(struct afb_session *session, const void *key, void *value, void (*freecb)(void*))
+{
+       struct cookie *cookie;
+
+       /* search for a replacement */
+       cookie = session->cookies;
+       while(cookie != NULL) {
+               if (cookie->key == key) {
+                       if (cookie->value != NULL && cookie->value != value && cookie->freecb != NULL)
+                               cookie->freecb(cookie->value);
+                       cookie->value = value;
+                       cookie->freecb = freecb;
+                       return 0;
+               }
+               cookie = cookie->next;
+       }
+
+       /* allocates */
+       cookie = malloc(sizeof *cookie);
+       if (cookie == NULL) {
+               errno = ENOMEM;
+               return -1;
+       }
+
+       cookie->key = key;
+       cookie->value = value;
+       cookie->freecb = freecb;
+       cookie->next = session->cookies;
+       session->cookies = cookie;
+       return 0;
+}
+
diff --git a/src/afb-session.h b/src/afb-session.h
new file mode 100644 (file)
index 0000000..7b3a710
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2016, 2017 "IoT.bzh"
+ * Author: José Bollo <jose.bollo@iot.bzh>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+struct json_object;
+struct afb_session;
+
+extern void afb_session_init(int max_session_count, int timeout, const char *initok, int context_count);
+
+extern struct afb_session *afb_session_create (const char *uuid, int timeout);
+extern struct afb_session *afb_session_get (const char *uuid, int *created);
+extern const char *afb_session_uuid (struct afb_session *session);
+
+extern struct afb_session *afb_session_addref(struct afb_session *session);
+extern void afb_session_unref(struct afb_session *session);
+
+extern void afb_session_close(struct afb_session *session);
+
+extern int afb_session_check_token(struct afb_session *session, const char *token);
+extern void afb_session_new_token(struct afb_session *session);
+extern const char *afb_session_token(struct afb_session *session);
+
+extern unsigned afb_session_get_LOA(struct afb_session *session);
+extern void afb_session_set_LOA (struct afb_session *session, unsigned loa);
+
+extern void *afb_session_get_value(struct afb_session *session, int index);
+extern void afb_session_set_value(struct afb_session *session, int index, void *value, void (*freecb)(void*));
+
+extern void *afb_session_get_cookie(struct afb_session *session, const void *key);
+extern int afb_session_set_cookie(struct afb_session *session, const void *key, void *value, void (*freecb)(void*));
+
index 4038218..c52ad65 100644 (file)
@@ -24,7 +24,7 @@
 #include <afb/afb-req-itf.h>
 #include <afb/afb-service-itf.h>
 
-#include "session.h"
+#include "afb-session.h"
 #include "afb-context.h"
 #include "afb-evt.h"
 #include "afb-subcall.h"
@@ -36,7 +36,7 @@
 struct afb_svc
 {
        /* session of the service */
-       struct AFB_clientCtx *session;
+       struct afb_session *session;
 
        /* event listener of the service or NULL */
        struct afb_evt_listener *listener;
@@ -100,8 +100,8 @@ const struct afb_req_itf afb_svc_req_itf = {
        .subcall = (void*)svcreq_subcall
 };
 
-/* the common session for services sahring their session */
-static struct AFB_clientCtx *common_session;
+/* the common session for services sharing their session */
+static struct afb_session *common_session;
 
 /*
  * Creates a new service
@@ -120,14 +120,14 @@ struct afb_svc *afb_svc_create(int share_session, int (*init)(struct afb_service
        if (share_session) {
                /* session shared with other svcs */
                if (common_session == NULL) {
-                       common_session = ctxClientCreate (NULL, 0);
+                       common_session = afb_session_create (NULL, 0);
                        if (common_session == NULL)
                                goto error2;
                }
-               svc->session = ctxClientAddRef(common_session);
+               svc->session = afb_session_addref(common_session);
        } else {
                /* session dedicated to the svc */
-               svc->session = ctxClientCreate (NULL, 0);
+               svc->session = afb_session_create (NULL, 0);
                if (svc->session == NULL)
                        goto error2;
        }
@@ -153,7 +153,7 @@ error4:
        if (svc->listener != NULL)
                afb_evt_listener_unref(svc->listener);
 error3:
-       ctxClientUnref(svc->session);
+       afb_session_unref(svc->session);
 error2:
        free(svc);
 error:
index ce0ae29..f383868 100644 (file)
@@ -31,7 +31,7 @@
 #include "afb-ws-json1.h"
 #include "afb-common.h"
 #include "afb-msg-json.h"
-#include "session.h"
+#include "afb-session.h"
 #include "afb-apis.h"
 #include "afb-context.h"
 #include "afb-evt.h"
@@ -66,7 +66,7 @@ struct afb_ws_json1
        int refcount;
        void (*cleanup)(void*);
        void *cleanup_closure;
-       struct AFB_clientCtx *session;
+       struct afb_session *session;
        struct afb_evt_listener *listener;
        struct afb_wsj1 *wsj1;
        int new_session;
@@ -139,7 +139,7 @@ struct afb_ws_json1 *afb_ws_json1_create(int fd, struct afb_context *context, vo
        result->refcount = 1;
        result->cleanup = cleanup;
        result->cleanup_closure = cleanup_closure;
-       result->session = ctxClientAddRef(context->session);
+       result->session = afb_session_addref(context->session);
        result->new_session = context->created != 0;
        if (result->session == NULL)
                goto error2;
@@ -157,7 +157,7 @@ struct afb_ws_json1 *afb_ws_json1_create(int fd, struct afb_context *context, vo
 error4:
        afb_wsj1_unref(result->wsj1);
 error3:
-       ctxClientUnref(result->session);
+       afb_session_unref(result->session);
 error2:
        free(result);
 error:
@@ -178,7 +178,7 @@ static void aws_unref(struct afb_ws_json1 *ws)
                afb_wsj1_unref(ws->wsj1);
                if (ws->cleanup != NULL)
                        ws->cleanup(ws->cleanup_closure);
-               ctxClientUnref(ws->session);
+               afb_session_unref(ws->session);
                free(ws);
        }
 }
index 4a074ee..b05c31c 100644 (file)
@@ -40,7 +40,7 @@
 #include "afb-hreq.h"
 #include "afb-sig-handler.h"
 #include "afb-thread.h"
-#include "session.h"
+#include "afb-session.h"
 #include "verbose.h"
 #include "afb-common.h"
 #include "afb-hook.h"
@@ -662,7 +662,7 @@ int main(int argc, char *argv[])  {
   start_items(config->items);
   config->items = NULL;
 
-  ctxStoreInit(config->nbSessionMax, config->cntxTimeout, config->token, afb_apis_count());
+  afb_session_init(config->nbSessionMax, config->cntxTimeout, config->token, afb_apis_count());
   if (!afb_hreq_init_cookie(config->httpdPort, config->rootapi, DEFLT_CNTX_TIMEOUT)) {
      ERROR("initialisation of cookies failed");
      exit (1);
diff --git a/src/session.c b/src/session.c
deleted file mode 100644 (file)
index 7e1e4c6..0000000
+++ /dev/null
@@ -1,460 +0,0 @@
-/*
- * Copyright (C) 2015, 2016, 2017 "IoT.bzh"
- * Author "Fulup Ar Foll"
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define _GNU_SOURCE
-#include <stdio.h>
-#include <time.h>
-#include <pthread.h>
-#include <stdlib.h>
-#include <string.h>
-#include <uuid/uuid.h>
-#include <assert.h>
-#include <errno.h>
-
-#include <json-c/json.h>
-
-#include "session.h"
-#include "verbose.h"
-
-#define NOW (time(NULL))
-
-struct client_value
-{
-       void *value;
-       void (*free_value)(void*);
-};
-
-struct cookie
-{
-       struct cookie *next;
-       const void *key;
-       void *value;
-       void (*free_value)(void*);
-};
-
-struct AFB_clientCtx
-{
-       unsigned refcount;
-       unsigned loa;
-       int timeout;
-       time_t expiration;    // expiration time of the token
-       time_t access;
-       char uuid[37];        // long term authentication of remote client
-       char token[37];       // short term authentication of remote client
-       struct client_value *values;
-       struct cookie *cookies;
-};
-
-// 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
-  struct AFB_clientCtx **store;          // sessions store
-  int count;                      // current number of sessions
-  int max;
-  int timeout;
-  int apicount;
-  char initok[37];
-} sessions;
-
-/* generate a uuid */
-static void new_uuid(char uuid[37])
-{
-       uuid_t newuuid;
-       uuid_generate(newuuid);
-       uuid_unparse_lower(newuuid, uuid);
-}
-
-// Free context [XXXX Should be protected again memory abort XXXX]
-static void ctxUuidFreeCB (struct AFB_clientCtx *client)
-{
-       int idx;
-       struct cookie *cookie;
-
-       // If application add a handle let's free it now
-       assert (client->values != NULL);
-
-       // Free client handle with a standard Free function, with app callback or ignore it
-       for (idx=0; idx < sessions.apicount; idx ++)
-               ctxClientValueSet(client, idx, NULL, NULL);
-
-       // free cookies
-       cookie = client->cookies;
-       while (cookie != NULL) {
-               client->cookies = cookie->next;
-               if (cookie->value != NULL && cookie->free_value != NULL)
-                       cookie->free_value(cookie->value);
-               free(cookie);
-               cookie = client->cookies;
-       }
-}
-
-// Create a new store in RAM, not that is too small it will be automatically extended
-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)max_session_count, sizeof(struct AFB_clientCtx));
-       sessions.max = max_session_count;
-       sessions.timeout = timeout;
-       sessions.apicount = context_count;
-       if (initok == NULL)
-               /* without token, a secret is made to forbid creation of sessions */
-               new_uuid(sessions.initok);
-       else if (strlen(initok) < sizeof(sessions.store[0]->token))
-               strcpy(sessions.initok, initok);
-       else {
-               ERROR("initial token '%s' too long (max length 36)", initok);
-               exit(1);
-       }
-}
-
-static struct AFB_clientCtx *ctxStoreSearch (const char* uuid)
-{
-    int  idx;
-    struct AFB_clientCtx *client;
-
-    assert (uuid != NULL);
-
-    pthread_mutex_lock(&sessions.mutex);
-
-    for (idx=0; idx < sessions.max; idx++) {
-       client = sessions.store[idx];
-        if (client && (0 == strcmp (uuid, client->uuid)))
-               goto found;
-    }
-    client = NULL;
-
-found:
-    pthread_mutex_unlock(&sessions.mutex);
-    return client;
-}
-
-static int ctxStoreDel (struct AFB_clientCtx *client)
-{
-    int idx;
-    int status;
-
-    assert (client != NULL);
-
-    pthread_mutex_lock(&sessions.mutex);
-
-    for (idx=0; idx < sessions.max; idx++) {
-        if (sessions.store[idx] == client) {
-               sessions.store[idx] = NULL;
-               sessions.count--;
-               status = 1;
-               goto deleted;
-       }
-    }
-    status = 0;
-deleted:
-    pthread_mutex_unlock(&sessions.mutex);
-    return status;
-}
-
-static int ctxStoreAdd (struct AFB_clientCtx *client)
-{
-    int idx;
-    int status;
-
-    assert (client != NULL);
-
-    pthread_mutex_lock(&sessions.mutex);
-
-    for (idx=0; idx < sessions.max; idx++) {
-        if (NULL == sessions.store[idx]) {
-               sessions.store[idx] = client;
-               sessions.count++;
-               status = 1;
-               goto added;
-       }
-    }
-    status = 0;
-added:
-    pthread_mutex_unlock(&sessions.mutex);
-    return status;
-}
-
-// Check if context timeout or not
-static int ctxStoreTooOld (struct AFB_clientCtx *ctx, time_t now)
-{
-    assert (ctx != NULL);
-    return ctx->expiration < now;
-}
-
-// Check if context is active or not
-static int ctxIsActive (struct AFB_clientCtx *ctx, time_t now)
-{
-    assert (ctx != NULL);
-    return ctx->uuid[0] != 0 && ctx->expiration >= now;
-}
-
-// Loop on every entry and remove old context sessions.hash
-static void ctxStoreCleanUp (time_t now)
-{
-       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);
-               }
-       }
-}
-
-static struct AFB_clientCtx *new_context (const char *uuid, int timeout, time_t now)
-{
-       struct AFB_clientCtx *clientCtx;
-
-       /* allocates a new one */
-        clientCtx = calloc(1, sizeof(struct AFB_clientCtx) + ((unsigned)sessions.apicount * sizeof(*clientCtx->values)));
-       if (clientCtx == NULL) {
-               errno = ENOMEM;
-               goto error;
-       }
-        clientCtx->values = (void*)(clientCtx + 1);
-
-       /* generate the uuid */
-       if (uuid == NULL) {
-               new_uuid(clientCtx->uuid);
-       } else {
-               if (strlen(uuid) >= sizeof clientCtx->uuid) {
-                       errno = EINVAL;
-                       goto error2;
-               }
-               strcpy(clientCtx->uuid, uuid);
-       }
-
-       /* init the token */
-       strcpy(clientCtx->token, sessions.initok);
-       clientCtx->timeout = timeout;
-       if (timeout != 0)
-               clientCtx->expiration = now + timeout;
-       else {
-               clientCtx->expiration = (time_t)(~(time_t)0);
-               if (clientCtx->expiration < 0)
-                       clientCtx->expiration = (time_t)(((unsigned long long)clientCtx->expiration) >> 1);
-       }
-       if (!ctxStoreAdd (clientCtx)) {
-               errno = ENOMEM;
-               goto error2;
-       }
-
-       clientCtx->access = now;
-       clientCtx->refcount = 1;
-       return clientCtx;
-
-error2:
-       free(clientCtx);
-error:
-       return NULL;
-}
-
-struct AFB_clientCtx *ctxClientCreate (const char *uuid, int timeout)
-{
-       time_t now;
-
-       /* cleaning */
-       now = NOW;
-       ctxStoreCleanUp (now);
-
-       /* search for an existing one not too old */
-       if (uuid != NULL && ctxStoreSearch(uuid) != NULL) {
-               errno = EEXIST;
-               return NULL;
-       }
-
-       return new_context(uuid, timeout, now);
-}
-
-// This function will return exiting client context or newly created client context
-struct AFB_clientCtx *ctxClientGetSession (const char *uuid, int *created)
-{
-       struct AFB_clientCtx *clientCtx;
-       time_t now;
-
-       /* cleaning */
-       now = NOW;
-       ctxStoreCleanUp (now);
-
-       /* search for an existing one not too old */
-       if (uuid != NULL) {
-               clientCtx = ctxStoreSearch(uuid);
-               if (clientCtx != NULL) {
-                       *created = 0;
-                       clientCtx->access = now;
-                       clientCtx->refcount++;
-                       return clientCtx;
-               }
-       }
-
-       *created = 1;
-       return new_context(uuid, sessions.timeout, now);
-}
-
-struct AFB_clientCtx *ctxClientAddRef(struct AFB_clientCtx *clientCtx)
-{
-       if (clientCtx != NULL)
-               clientCtx->refcount++;
-       return clientCtx;
-}
-
-void ctxClientUnref(struct AFB_clientCtx *clientCtx)
-{
-       if (clientCtx != NULL) {
-               assert(clientCtx->refcount != 0);
-               --clientCtx->refcount;
-                       if (clientCtx->refcount == 0 && clientCtx->uuid[0] == 0) {
-                       ctxStoreDel (clientCtx);
-                       free(clientCtx);
-               }
-       }
-}
-
-// Free Client Session Context
-void ctxClientClose (struct AFB_clientCtx *clientCtx)
-{
-       assert(clientCtx != NULL);
-       if (clientCtx->uuid[0] != 0) {
-               clientCtx->uuid[0] = 0;
-               ctxUuidFreeCB (clientCtx);
-                       if (clientCtx->refcount == 0) {
-                       ctxStoreDel (clientCtx);
-                       free(clientCtx);
-               }
-       }
-}
-
-// Sample Generic Ping Debug API
-int ctxTokenCheck (struct AFB_clientCtx *clientCtx, const char *token)
-{
-       assert(clientCtx != NULL);
-       assert(token != NULL);
-
-       // compare current token with previous one
-       if (!ctxIsActive (clientCtx, NOW))
-               return 0;
-
-       if (clientCtx->token[0] && strcmp (token, clientCtx->token) != 0)
-               return 0;
-
-       return 1;
-}
-
-// generate a new token and update client context
-void ctxTokenNew (struct AFB_clientCtx *clientCtx)
-{
-       assert(clientCtx != NULL);
-
-       // Old token was valid let's regenerate a new one
-       new_uuid(clientCtx->token);
-
-       // keep track of time for session timeout and further clean up
-       if (clientCtx->timeout != 0)
-               clientCtx->expiration = NOW + clientCtx->timeout;
-}
-
-const char *ctxClientGetUuid (struct AFB_clientCtx *clientCtx)
-{
-       assert(clientCtx != NULL);
-       return clientCtx->uuid;
-}
-
-const char *ctxClientGetToken (struct AFB_clientCtx *clientCtx)
-{
-       assert(clientCtx != NULL);
-       return clientCtx->token;
-}
-
-unsigned ctxClientGetLOA (struct AFB_clientCtx *clientCtx)
-{
-       assert(clientCtx != NULL);
-       return clientCtx->loa;
-}
-
-void ctxClientSetLOA (struct AFB_clientCtx *clientCtx, unsigned loa)
-{
-       assert(clientCtx != NULL);
-       clientCtx->loa = loa;
-}
-
-void *ctxClientValueGet(struct AFB_clientCtx *clientCtx, int index)
-{
-       assert(clientCtx != NULL);
-       assert(index >= 0);
-       assert(index < sessions.apicount);
-       return clientCtx->values[index].value;
-}
-
-void ctxClientValueSet(struct AFB_clientCtx *clientCtx, int index, void *value, void (*free_value)(void*))
-{
-       struct client_value prev;
-       assert(clientCtx != NULL);
-       assert(index >= 0);
-       assert(index < sessions.apicount);
-       prev = clientCtx->values[index];
-       clientCtx->values[index] = (struct client_value){.value = value, .free_value = free_value};
-       if (prev.value != NULL && prev.value != value && prev.free_value != NULL)
-               prev.free_value(prev.value);
-}
-
-void *ctxClientCookieGet(struct AFB_clientCtx *clientCtx, const void *key)
-{
-       struct cookie *cookie;
-
-       cookie = clientCtx->cookies;
-       while(cookie != NULL) {
-               if (cookie->key == key)
-                       return cookie->value;
-               cookie = cookie->next;
-       }
-       return NULL;
-}
-
-int ctxClientCookieSet(struct AFB_clientCtx *clientCtx, const void *key, void *value, void (*free_value)(void*))
-{
-       struct cookie *cookie;
-
-       /* search for a replacement */
-       cookie = clientCtx->cookies;
-       while(cookie != NULL) {
-               if (cookie->key == key) {
-                       if (cookie->value != NULL && cookie->value != value && cookie->free_value != NULL)
-                               cookie->free_value(cookie->value);
-                       cookie->value = value;
-                       cookie->free_value = free_value;
-                       return 0;
-               }
-               cookie = cookie->next;
-       }
-
-       /* allocates */
-       cookie = malloc(sizeof *cookie);
-       if (cookie == NULL) {
-               errno = ENOMEM;
-               return -1;
-       }
-
-       cookie->key = key;
-       cookie->value = value;
-       cookie->free_value = free_value;
-       cookie->next = clientCtx->cookies;
-       clientCtx->cookies = cookie;
-       return 0;
-}
-
diff --git a/src/session.h b/src/session.h
deleted file mode 100644 (file)
index 2399324..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2016, 2017 "IoT.bzh"
- * Author: José Bollo <jose.bollo@iot.bzh>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-struct json_object;
-struct AFB_clientCtx;
-
-extern void ctxStoreInit (int max_session_count, int timeout, const char *initok, int context_count);
-
-extern struct AFB_clientCtx *ctxClientCreate (const char *uuid, int timeout);
-extern struct AFB_clientCtx *ctxClientGetSession (const char *uuid, int *created);
-extern struct AFB_clientCtx *ctxClientAddRef(struct AFB_clientCtx *clientCtx);
-extern void ctxClientUnref(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);
-
-extern const char *ctxClientGetUuid (struct AFB_clientCtx *clientCtx);
-extern const char *ctxClientGetToken (struct AFB_clientCtx *clientCtx);
-extern unsigned ctxClientGetLOA (struct AFB_clientCtx *clientCtx);
-extern void ctxClientSetLOA (struct AFB_clientCtx *clientCtx, unsigned loa);
-
-extern void *ctxClientValueGet(struct AFB_clientCtx *clientCtx, int index);
-extern void ctxClientValueSet(struct AFB_clientCtx *clientCtx, int index, void *value, void (*free_value)(void*));
-
-extern void *ctxClientCookieGet(struct AFB_clientCtx *clientCtx, const void *key);
-extern int ctxClientCookieSet(struct AFB_clientCtx *clientCtx, const void *key, void *value, void (*free_value)(void*));
-