X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fafb-session.c;h=523cbf0444c9e298bd86e30efe79a7b306d3af66;hb=bd4f365ba69281941c14b2c02d58f4b37a22b42d;hp=db81457cf34c5eca974e8c219399d808cddc87ae;hpb=a758d774aa5dacc07d2840f1b7ccef793863389f;p=src%2Fapp-framework-binder.git diff --git a/src/afb-session.c b/src/afb-session.c index db81457c..523cbf04 100644 --- a/src/afb-session.c +++ b/src/afb-session.c @@ -31,13 +31,10 @@ #include "afb-session.h" #include "verbose.h" -#define NOW (time(NULL)) +#define COOKEYCOUNT 8 +#define COOKEYMASK (COOKEYCOUNT - 1) -struct value -{ - void *value; - void (*freecb)(void*); -}; +#define NOW (time(NULL)) struct cookie { @@ -50,14 +47,13 @@ struct cookie struct afb_session { unsigned refcount; - unsigned loa; 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 value *values; - struct cookie *cookies; + struct cookie *cookies[COOKEYCOUNT]; }; // Session UUID are store in a simple array [for 10 sessions this should be enough] @@ -67,10 +63,21 @@ static struct { int count; // current number of sessions int max; int timeout; - int apicount; char initok[37]; } sessions; +/** + * Get the index of the 'key' in the cookies array. + * @param key the key to scan + * @return the index of the list for key within cookies + */ +static int cookeyidx(const void *key) +{ + intptr_t x = (intptr_t)key; + unsigned r = (unsigned)((x >> 5) ^ (x >> 15)); + return r & COOKEYMASK; +} + /* generate a uuid */ static void new_uuid(char uuid[37]) { @@ -79,38 +86,44 @@ 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) { 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); + struct cookie *cookie, *next; // 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; + for (idx = 0 ; idx < COOKEYCOUNT ; idx++) { + cookie = session->cookies[idx]; + session->cookies[idx] = NULL; + while (cookie != NULL) { + next = cookie->next; + if (cookie->freecb != NULL) + cookie->freecb(cookie->value); + free(cookie); + cookie = next; + } } } // 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) +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; - sessions.apicount = context_count; if (initok == NULL) /* without token, a secret is made to forbid creation of sessions */ new_uuid(sessions.initok); @@ -223,12 +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) + ((unsigned)sessions.apicount * sizeof(*session->values))); + session = calloc(1, sizeof *session); if (session == NULL) { errno = ENOMEM; goto error; } - session->values = (void*)(session + 1); + 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,80 +396,87 @@ const char *afb_session_token (struct afb_session *session) return session->token; } -unsigned afb_session_get_LOA (struct afb_session *session) +static struct cookie *cookie_search(struct afb_session *session, const void *key, int *idx) { - assert(session != NULL); - return session->loa; -} + struct cookie *cookie; -void afb_session_set_LOA (struct afb_session *session, unsigned loa) -{ - assert(session != NULL); - session->loa = loa; + cookie = session->cookies[*idx = cookeyidx(key)]; + while(cookie != NULL && cookie->key != key) + cookie = cookie->next; + return cookie; } -void *afb_session_get_value(struct afb_session *session, int index) +static struct cookie *cookie_add(struct afb_session *session, int idx, const void *key, void *value, void (*freecb)(void*)) { - assert(session != NULL); - assert(index >= 0); - assert(index < sessions.apicount); - return session->values[index].value; + 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_set_value(struct afb_session *session, int index, void *value, void (*freecb)(void*)) +void *afb_session_cookie(struct afb_session *session, const void *key, void *(*makecb)(void), 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); + int idx; + void *value; + struct cookie *cookie; + + 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; + } + } + } + unlock(session); + return value; } void *afb_session_get_cookie(struct afb_session *session, const void *key) { + int idx; + void *value; struct cookie *cookie; - cookie = session->cookies; - while(cookie != NULL) { - if (cookie->key == key) - return cookie->value; - cookie = cookie->next; - } - return NULL; + 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; - /* 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; + 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; } - - cookie->key = key; - cookie->value = value; - cookie->freecb = freecb; - cookie->next = session->cookies; - session->cookies = cookie; - return 0; + unlock(session); + return -!cookie; }