X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fafb-session.c;h=536cdbccd46d6faa1e2c31cbc2035dc816122c12;hb=b596b217c9b82d6be2b1d5486cdced31831aebc3;hp=07092cea80d8a49e3b92b98d4ee38c05968947eb;hpb=25a84c46729699668725da1214f7f8c829b1498e;p=src%2Fapp-framework-binder.git diff --git a/src/afb-session.c b/src/afb-session.c index 07092cea..536cdbcc 100644 --- a/src/afb-session.c +++ b/src/afb-session.c @@ -47,10 +47,10 @@ 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 cookie *cookies[COOKEYCOUNT]; @@ -86,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) { @@ -98,7 +108,7 @@ static void free_data (struct afb_session *session) session->cookies[idx] = NULL; while (cookie != NULL) { next = cookie->next; - if (cookie->value != NULL && cookie->freecb != NULL) + if (cookie->freecb != NULL) cookie->freecb(cookie->value); free(cookie); cookie = next; @@ -111,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) @@ -225,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) { @@ -312,7 +324,7 @@ struct afb_session *afb_session_get (const char *uuid, int *created) 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; } @@ -320,10 +332,12 @@ 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); + if (!__atomic_sub_fetch(&session->refcount, 1, __ATOMIC_RELAXED)) { + if (session->uuid[0] == 0) { + destroy (session); + pthread_mutex_destroy(&session->mutex); + free(session); + } } } } @@ -383,64 +397,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_cookie(struct afb_session *session, const void *key) +static struct cookie *cookie_add(struct afb_session *session, int idx, const void *key, void *value, void (*freecb)(void*)) { 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; + 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 NULL; + return cookie; } -int afb_session_set_cookie(struct afb_session *session, const void *key, void *value, void (*freecb)(void*)) +void *afb_session_cookie(struct afb_session *session, const void *key, void *(*makecb)(void), void (*freecb)(void*)) { - struct cookie *cookie; 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 != NULL && cookie->value != value && cookie->freecb != NULL) - 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; +} - 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*)) +{ + 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; }