summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/CMakeLists.txt2
-rw-r--r--src/afb-api-dbus.c12
-rw-r--r--src/afb-api-so.c2
-rw-r--r--src/afb-api-ws.c4
-rw-r--r--src/afb-apis.c2
-rw-r--r--src/afb-config.h3
-rw-r--r--src/afb-context.c34
-rw-r--r--src/afb-context.h6
-rw-r--r--src/afb-evt.h2
-rw-r--r--src/afb-hook.c12
-rw-r--r--src/afb-hook.h4
-rw-r--r--src/afb-hreq.c2
-rw-r--r--src/afb-hreq.h2
-rw-r--r--src/afb-hswitch.c2
-rw-r--r--src/afb-session.c461
-rw-r--r--src/afb-session.h46
-rw-r--r--src/afb-svc.c16
-rw-r--r--src/afb-ws-json1.c10
-rw-r--r--src/main.c4
-rw-r--r--src/session.c460
-rw-r--r--src/session.h44
21 files changed, 565 insertions, 565 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 80d09bfe..0fcfba67 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -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
)
diff --git a/src/afb-api-dbus.c b/src/afb-api-dbus.c
index 9ebe1fad..4a5a4f1f 100644
--- a/src/afb-api-dbus.c
+++ b/src/afb-api-dbus.c
@@ -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 */
diff --git a/src/afb-api-so.c b/src/afb-api-so.c
index 554df39a..74f94f36 100644
--- a/src/afb-api-so.c
+++ b/src/afb-api-so.c
@@ -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"
diff --git a/src/afb-api-ws.c b/src/afb-api-ws.c
index cb7b4f58..4d1f08c8 100644
--- a/src/afb-api-ws.c
+++ b/src/afb-api-ws.c
@@ -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;
diff --git a/src/afb-apis.c b/src/afb-apis.c
index 6bc42779..7db3e75a 100644
--- a/src/afb-apis.c
+++ b/src/afb-apis.c
@@ -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"
diff --git a/src/afb-config.h b/src/afb-config.h
index 9ff4cd64..7bbad4df 100644
--- a/src/afb-config.h
+++ b/src/afb-config.h
@@ -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 */
diff --git a/src/afb-context.c b/src/afb-context.c
index 0bcc79c3..eec4ebb0 100644
--- a/src/afb-context.c
+++ b/src/afb-context.c
@@ -21,10 +21,10 @@
#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)
diff --git a/src/afb-context.h b/src/afb-context.h
index 35709e20..d65e6ffa 100644
--- a/src/afb-context.h
+++ b/src/afb-context.h
@@ -17,11 +17,11 @@
#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);
diff --git a/src/afb-evt.h b/src/afb-evt.h
index bd765b8c..52b40ab1 100644
--- a/src/afb-evt.h
+++ b/src/afb-evt.h
@@ -18,7 +18,7 @@
#pragma once
struct afb_event;
-struct AFB_clientCtx;
+struct afb_session;
struct afb_evt_listener;
diff --git a/src/afb-hook.c b/src/afb-hook.c
index f7d3e5b4..d5c534d0 100644
--- a/src/afb-hook.c
+++ b/src/afb-hook.c
@@ -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);
}
}
diff --git a/src/afb-hook.h b/src/afb-hook.h
index ae6ef832..2ad01b85 100644
--- a/src/afb-hook.h
+++ b/src/afb-hook.h
@@ -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);
diff --git a/src/afb-hreq.c b/src/afb-hreq.c
index b0f1172e..b2180458 100644
--- a/src/afb-hreq.c
+++ b/src/afb-hreq.c
@@ -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"
diff --git a/src/afb-hreq.h b/src/afb-hreq.h
index 72cefcf1..f07f2fa6 100644
--- a/src/afb-hreq.h
+++ b/src/afb-hreq.h
@@ -17,7 +17,7 @@
#pragma once
-struct AFB_clientCtx;
+struct afb_session;
struct json_object;
struct hreq_data;
struct afb_hsrv;
diff --git a/src/afb-hswitch.c b/src/afb-hswitch.c
index 90dc2ffa..9c929e83 100644
--- a/src/afb-hswitch.c
+++ b/src/afb-hswitch.c
@@ -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
index 00000000..db81457c
--- /dev/null
+++ b/src/afb-session.c
@@ -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
index 00000000..7b3a7101
--- /dev/null
+++ b/src/afb-session.h
@@ -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*));
+
diff --git a/src/afb-svc.c b/src/afb-svc.c
index 4038218c..c52ad654 100644
--- a/src/afb-svc.c
+++ b/src/afb-svc.c
@@ -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:
diff --git a/src/afb-ws-json1.c b/src/afb-ws-json1.c
index ce0ae29f..f383868a 100644
--- a/src/afb-ws-json1.c
+++ b/src/afb-ws-json1.c
@@ -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);
}
}
diff --git a/src/main.c b/src/main.c
index 4a074eee..b05c31ca 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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
index 7e1e4c68..00000000
--- a/src/session.c
+++ /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
index 23993248..00000000
--- a/src/session.h
+++ /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*));
-