aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosé Bollo <jose.bollo@iot.bzh>2017-05-05 12:04:25 +0200
committerJosé Bollo <jose.bollo@iot.bzh>2017-05-05 12:12:05 +0200
commitce8de8236b96dc771d3af3094e04e797e75767af (patch)
tree37bf561a8a183aea5fa035200414f3575ad24121
parente97aa93b02793018d7d9cad1582748b02493dad2 (diff)
session: start to manage concurrency
Change-Id: I5895fa14fcb496e71fba600994e7e454cf1d110b Signed-off-by: José Bollo <jose.bollo@iot.bzh>
-rw-r--r--bindings/samples/DemoContext.c8
-rw-r--r--src/afb-context.c6
-rw-r--r--src/afb-context.h1
-rw-r--r--src/afb-session.c117
-rw-r--r--src/afb-session.h1
5 files changed, 99 insertions, 34 deletions
diff --git a/bindings/samples/DemoContext.c b/bindings/samples/DemoContext.c
index 66dc6ccf..26677949 100644
--- a/bindings/samples/DemoContext.c
+++ b/bindings/samples/DemoContext.c
@@ -67,6 +67,10 @@ static void myAction (struct afb_req request)
{
MyClientContextT *ctx = (MyClientContextT*) afb_req_context_get(request);
+ if (!ctx) {
+ afb_req_fail(request, "invalid-state", "Can't perform action");
+ return;
+ }
// store something in our plugin private client context
ctx->count++;
afb_req_success_f(request, NULL, "SUCCESS: plugin [%s] Check=[%d]\n", ctx->abcd, ctx->count);
@@ -80,6 +84,10 @@ static void myClose (struct afb_req request)
{
MyClientContextT *ctx = (MyClientContextT*) afb_req_context_get(request);
+ if (!ctx) {
+ afb_req_success(request, NULL, NULL);
+ return;
+ }
// store something in our plugin private client context
ctx->count++;
afb_req_success_f(request, NULL, "SUCCESS: plugin [%s] Close=[%d]\n", ctx->abcd, ctx->count);
diff --git a/src/afb-context.c b/src/afb-context.c
index 9f5ddd3c..83ce5733 100644
--- a/src/afb-context.c
+++ b/src/afb-context.c
@@ -109,6 +109,12 @@ const char *afb_context_sent_uuid(struct afb_context *context)
return afb_session_uuid(context->session);
}
+void *afb_context_data(struct afb_context *context, void *(*make_value)(void), void (*free_value)(void*))
+{
+ assert(context->session != NULL);
+ return afb_session_cookie(context->session, context->api_key, make_value, free_value);
+}
+
void *afb_context_get(struct afb_context *context)
{
assert(context->session != NULL);
diff --git a/src/afb-context.h b/src/afb-context.h
index ceda5d24..55605858 100644
--- a/src/afb-context.h
+++ b/src/afb-context.h
@@ -47,6 +47,7 @@ extern const char *afb_context_sent_uuid(struct afb_context *context);
extern void *afb_context_get(struct afb_context *context);
extern void afb_context_set(struct afb_context *context, void *value, void (*free_value)(void*));
+extern void *afb_context_data(struct afb_context *context, void *(*make_value)(void), void (*free_value)(void*));
extern void afb_context_close(struct afb_context *context);
extern void afb_context_refresh(struct afb_context *context);
diff --git a/src/afb-session.c b/src/afb-session.c
index 17fddd5c..523cbf04 100644
--- a/src/afb-session.c
+++ b/src/afb-session.c
@@ -50,6 +50,7 @@ struct afb_session
int timeout;
time_t expiration; // expiration time of the token
time_t access;
+ pthread_mutex_t mutex;
char uuid[37]; // long term authentication of remote client
char token[37]; // short term authentication of remote client
struct cookie *cookies[COOKEYCOUNT];
@@ -85,6 +86,16 @@ static void new_uuid(char uuid[37])
uuid_unparse_lower(newuuid, uuid);
}
+static inline void lock(struct afb_session *session)
+{
+ pthread_mutex_lock(&session->mutex);
+}
+
+static inline void unlock(struct afb_session *session)
+{
+ pthread_mutex_unlock(&session->mutex);
+}
+
// Free context [XXXX Should be protected again memory abort XXXX]
static void free_data (struct afb_session *session)
{
@@ -110,6 +121,7 @@ void afb_session_init (int max_session_count, int timeout, const char *initok)
{
// let's create as store as hashtable does not have any
sessions.store = calloc (1 + (unsigned)max_session_count, sizeof(struct afb_session));
+ pthread_mutex_init(&sessions.mutex, NULL);
sessions.max = max_session_count;
sessions.timeout = timeout;
if (initok == NULL)
@@ -224,11 +236,12 @@ static struct afb_session *make_session (const char *uuid, int timeout, time_t n
struct afb_session *session;
/* allocates a new one */
- session = calloc(1, sizeof(struct afb_session));
+ session = calloc(1, sizeof *session);
if (session == NULL) {
errno = ENOMEM;
goto error;
}
+ pthread_mutex_init(&session->mutex, NULL);
/* generate the uuid */
if (uuid == NULL) {
@@ -322,6 +335,7 @@ void afb_session_unref(struct afb_session *session)
--session->refcount;
if (session->refcount == 0 && session->uuid[0] == 0) {
destroy (session);
+ pthread_mutex_destroy(&session->mutex);
free(session);
}
}
@@ -382,52 +396,87 @@ const char *afb_session_token (struct afb_session *session)
return session->token;
}
-void *afb_session_get_cookie(struct afb_session *session, const void *key)
+static struct cookie *cookie_search(struct afb_session *session, const void *key, int *idx)
{
struct cookie *cookie;
- int idx;
- idx = cookeyidx(key);
- cookie = session->cookies[idx];
- while(cookie != NULL) {
- if (cookie->key == key)
- return cookie->value;
+ cookie = session->cookies[*idx = cookeyidx(key)];
+ while(cookie != NULL && cookie->key != key)
cookie = cookie->next;
- }
- return NULL;
+ return cookie;
}
-int afb_session_set_cookie(struct afb_session *session, const void *key, void *value, void (*freecb)(void*))
+static struct cookie *cookie_add(struct afb_session *session, int idx, const void *key, void *value, void (*freecb)(void*))
{
struct cookie *cookie;
+
+ cookie = malloc(sizeof *cookie);
+ if (!cookie)
+ errno = ENOMEM;
+ else {
+ cookie->key = key;
+ cookie->value = value;
+ cookie->freecb = freecb;
+ cookie->next = session->cookies[idx];
+ session->cookies[idx] = cookie;
+ }
+ return cookie;
+}
+
+void *afb_session_cookie(struct afb_session *session, const void *key, void *(*makecb)(void), void (*freecb)(void*))
+{
int idx;
+ void *value;
+ struct cookie *cookie;
- /* search for a replacement */
- idx = cookeyidx(key);
- cookie = session->cookies[idx];
- while(cookie != NULL) {
- if (cookie->key == key) {
- if (cookie->value != value && cookie->freecb)
- cookie->freecb(cookie->value);
- cookie->value = value;
- cookie->freecb = freecb;
- return 0;
+ lock(session);
+ cookie = cookie_search(session, key, &idx);
+ if (cookie)
+ value = cookie->value;
+ else {
+ value = makecb ? makecb() : NULL;
+ if (makecb || freecb) {
+ cookie = cookie_add(session, idx, key, value, freecb);
+ if (!cookie) {
+ if (makecb && freecb)
+ free(value);
+ value = NULL;
+ }
}
- cookie = cookie->next;
}
+ unlock(session);
+ return value;
+}
- /* allocates */
- cookie = malloc(sizeof *cookie);
- if (cookie == NULL) {
- errno = ENOMEM;
- return -1;
- }
+void *afb_session_get_cookie(struct afb_session *session, const void *key)
+{
+ int idx;
+ void *value;
+ struct cookie *cookie;
+
+ lock(session);
+ cookie = cookie_search(session, key, &idx);
+ value = cookie ? cookie->value : NULL;
+ unlock(session);
+ return value;
+}
+
+int afb_session_set_cookie(struct afb_session *session, const void *key, void *value, void (*freecb)(void*))
+{
+ int idx;
+ struct cookie *cookie;
- cookie->key = key;
- cookie->value = value;
- cookie->freecb = freecb;
- cookie->next = session->cookies[idx];
- session->cookies[idx] = cookie;
- return 0;
+ lock(session);
+ cookie = cookie_search(session, key, &idx);
+ if (!cookie)
+ cookie = cookie_add(session, idx, key, value, freecb);
+ else {
+ if (cookie->value != value && cookie->freecb)
+ cookie->freecb(cookie->value);
+ cookie->value = value;
+ cookie->freecb = freecb;
+ }
+ unlock(session);
+ return -!cookie;
}
diff --git a/src/afb-session.h b/src/afb-session.h
index afff6714..e79d0376 100644
--- a/src/afb-session.h
+++ b/src/afb-session.h
@@ -35,5 +35,6 @@ extern void afb_session_new_token(struct afb_session *session);
extern const char *afb_session_token(struct afb_session *session);
extern void *afb_session_get_cookie(struct afb_session *session, const void *key);
+extern void *afb_session_cookie(struct afb_session *session, const void *key, void *(*makecb)(void), void (*freecb)(void*));
extern int afb_session_set_cookie(struct afb_session *session, const void *key, void *value, void (*freecb)(void*));