afb-session: remove unused access time
[src/app-framework-binder.git] / src / afb-session.c
index 536cdbc..68de672 100644 (file)
@@ -49,7 +49,6 @@ struct afb_session
        unsigned refcount;
        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
@@ -59,7 +58,7 @@ struct afb_session
 // 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
+       struct afb_session **store;     // sessions store
        int count;                      // current number of sessions
        int max;
        int timeout;
@@ -97,7 +96,7 @@ static inline void unlock(struct afb_session *session)
 }
 
 // Free context [XXXX Should be protected again memory abort XXXX]
-static void free_data (struct afb_session *session)
+static void remove_all_cookies(struct afb_session *session)
 {
        int idx;
        struct cookie *cookie, *next;
@@ -120,7 +119,7 @@ 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;
@@ -135,6 +134,11 @@ void afb_session_init (int max_session_count, int timeout, const char *initok)
        }
 }
 
+const char *afb_session_initial_token()
+{
+       return sessions.initok;
+}
+
 static struct afb_session *search (const char* uuid)
 {
        int  idx;
@@ -235,6 +239,12 @@ static struct afb_session *make_session (const char *uuid, int timeout, time_t n
 {
        struct afb_session *session;
 
+       if (!AFB_SESSION_TIMEOUT_IS_VALID(timeout)
+        || (uuid && strlen(uuid) >= sizeof session->uuid)) {
+               errno = EINVAL;
+               goto error;
+       }
+
        /* allocates a new one */
        session = calloc(1, sizeof *session);
        if (session == NULL) {
@@ -245,21 +255,20 @@ static struct afb_session *make_session (const char *uuid, int timeout, time_t n
 
        /* generate the uuid */
        if (uuid == NULL) {
-               new_uuid(session->uuid);
+               do { new_uuid(session->uuid); } while(search(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);
+
+       /* init timeout */
+       if (timeout == AFB_SESSION_TIMEOUT_DEFAULT)
+               timeout = sessions.timeout;
        session->timeout = timeout;
-       if (timeout != 0)
-               session->expiration = now + timeout;
-       else {
+       session->expiration = now + timeout;
+       if (timeout == AFB_SESSION_TIMEOUT_INFINITE || session->expiration < 0) {
                session->expiration = (time_t)(~(time_t)0);
                if (session->expiration < 0)
                        session->expiration = (time_t)(((unsigned long long)session->expiration) >> 1);
@@ -269,7 +278,6 @@ static struct afb_session *make_session (const char *uuid, int timeout, time_t n
                goto error2;
        }
 
-       session->access = now;
        session->refcount = 1;
        return session;
 
@@ -279,7 +287,8 @@ error:
        return NULL;
 }
 
-struct afb_session *afb_session_create (const char *uuid, int timeout)
+/* Creates a new session with 'timeout' */
+struct afb_session *afb_session_create (int timeout)
 {
        time_t now;
 
@@ -287,17 +296,25 @@ struct afb_session *afb_session_create (const char *uuid, int timeout)
        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(NULL, timeout, now);
+}
+
+/* Searchs the session of 'uuid' */
+struct afb_session *afb_session_search (const char *uuid)
+{
+       time_t now;
+       struct afb_session *session;
+
+       /* cleaning */
+       now = NOW;
+       cleanup (now);
+       session = search(uuid);
+       return session;
 
-       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)
+/* This function will return exiting session or newly created session */
+struct afb_session *afb_session_get (const char *uuid, int timeout, int *created)
 {
        struct afb_session *session;
        time_t now;
@@ -310,15 +327,19 @@ struct afb_session *afb_session_get (const char *uuid, int *created)
        if (uuid != NULL) {
                session = search(uuid);
                if (session != NULL) {
-                       *created = 0;
-                       session->access = now;
+                       if (created)
+                               *created = 0;
                        session->refcount++;
                        return session;
                }
        }
 
-       *created = 1;
-       return make_session(uuid, sessions.timeout, now);
+       /* no existing session found, create it */
+       session = make_session(uuid, timeout, now);
+       if (created)
+               *created = !!session;
+
+       return session;
 }
 
 struct afb_session *afb_session_addref(struct afb_session *session)
@@ -348,7 +369,7 @@ void afb_session_close (struct afb_session *session)
        assert(session != NULL);
        if (session->uuid[0] != 0) {
                session->uuid[0] = 0;
-               free_data (session);
+               remove_all_cookies(session);
                if (session->refcount == 0) {
                        destroy (session);
                        free(session);
@@ -385,64 +406,62 @@ void afb_session_new_token (struct afb_session *session)
                session->expiration = NOW + session->timeout;
 }
 
+/* Returns the uuid of 'session' */
 const char *afb_session_uuid (struct afb_session *session)
 {
        assert(session != NULL);
        return session->uuid;
 }
 
+/* Returns the token of 'session' */
 const char *afb_session_token (struct afb_session *session)
 {
        assert(session != NULL);
        return session->token;
 }
 
-static struct cookie *cookie_search(struct afb_session *session, const void *key, int *idx)
-{
-       struct cookie *cookie;
-
-       cookie = session->cookies[*idx = cookeyidx(key)];
-       while(cookie != NULL && cookie->key != key)
-               cookie = cookie->next;
-       return cookie;
-}
-
-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*))
+/* Set, get, replace, remove a cookie key */
+void *afb_session_cookie(struct afb_session *session, const void *key, void *(*makecb)(void *closure), void (*freecb)(void *item), void *closure, int replace)
 {
        int idx;
        void *value;
        struct cookie *cookie;
 
+       idx = cookeyidx(key);
        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 = session->cookies[idx];
+       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;
                }
        }
        unlock(session);
@@ -451,33 +470,11 @@ void *afb_session_cookie(struct afb_session *session, const void *key, void *(*m
 
 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;
+       return afb_session_cookie(session, key, NULL, NULL, NULL, 0);
 }
 
 int afb_session_set_cookie(struct afb_session *session, const void *key, void *value, void (*freecb)(void*))
 {
-       int idx;
-       struct cookie *cookie;
-
-       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;
+       return -(value != afb_session_cookie(session, key, NULL, freecb, value, 1));
 }