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];
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)
{
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));
+ sessions.store = calloc (1 + (unsigned)max_session_count, sizeof *sessions.store);
+ pthread_mutex_init(&sessions.mutex, NULL);
sessions.max = max_session_count;
sessions.timeout = timeout;
if (initok == NULL)
}
}
+const char *afb_session_initial_token()
+{
+ return sessions.initok;
+}
+
static struct afb_session *search (const char* uuid)
{
int idx;
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) {
/* search for an existing one not too old */
if (uuid != NULL) {
session = search(uuid);
+ if (!created)
+ return session;
if (session != NULL) {
*created = 0;
session->access = now;
}
}
- *created = 1;
+ if (created)
+ *created = 1;
+
return make_session(uuid, sessions.timeout, now);
}
struct afb_session *afb_session_addref(struct afb_session *session)
{
if (session != NULL)
- session->refcount++;
+ __atomic_add_fetch(&session->refcount, 1, __ATOMIC_RELAXED);
return session;
}
{
if (session != NULL) {
assert(session->refcount != 0);
- --session->refcount;
- if (session->refcount == 0 && session->uuid[0] == 0) {
- destroy (session);
- free(session);
+ if (!__atomic_sub_fetch(&session->refcount, 1, __ATOMIC_RELAXED)) {
+ if (session->uuid[0] == 0) {
+ destroy (session);
+ pthread_mutex_destroy(&session->mutex);
+ free(session);
+ }
}
}
}
return session->token;
}
-void *afb_session_get_cookie(struct afb_session *session, const void *key)
+void *afb_session_cookie(struct afb_session *session, const void *key, void *(*makecb)(void *closure), void (*freecb)(void *item), void *closure, int replace)
{
- struct cookie *cookie;
int idx;
-
- idx = cookeyidx(key);
- cookie = session->cookies[idx];
- 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*))
-{
+ void *value;
struct cookie *cookie;
- int idx;
- /* search for a replacement */
idx = cookeyidx(key);
+ lock(session);
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;
+ for (;;) {
+ if (!cookie) {
+ value = makecb ? makecb(closure) : closure;
+ if (replace || makecb || freecb) {
+ cookie = malloc(sizeof *cookie);
+ if (!cookie) {
+ errno = ENOMEM;
+ if (freecb)
+ freecb(value);
+ value = NULL;
+ } else {
+ cookie->key = key;
+ cookie->value = value;
+ cookie->freecb = freecb;
+ cookie->next = session->cookies[idx];
+ session->cookies[idx] = cookie;
+ }
+ }
+ break;
+ } else if (cookie->key == key) {
+ if (!replace)
+ value = cookie->value;
+ else {
+ value = makecb ? makecb(closure) : closure;
+ if (cookie->value != value && cookie->freecb)
+ cookie->freecb(cookie->value);
+ cookie->value = value;
+ cookie->freecb = freecb;
+ }
+ break;
+ } else {
+ cookie = cookie->next;
}
- 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)
+{
+ return afb_session_cookie(session, key, NULL, NULL, NULL, 0);
+}
- cookie->key = key;
- cookie->value = value;
- cookie->freecb = freecb;
- cookie->next = session->cookies[idx];
- session->cookies[idx] = cookie;
- return 0;
+int afb_session_set_cookie(struct afb_session *session, const void *key, void *value, void (*freecb)(void*))
+{
+ return -(value != afb_session_cookie(session, key, NULL, freecb, value, 1));
}