X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fafb-session.c;h=f0cf07440c22ebd4ac6d3fc3502046f5e45895c3;hb=b947c93689b2b93a02cdc427e58805d79a323116;hp=43e08d48cc0177e21ec7d7183d8450c2bd411256;hpb=ef3d8bddfd976643620f56471a4711cd0daa197f;p=src%2Fapp-framework-binder.git diff --git a/src/afb-session.c b/src/afb-session.c index 43e08d48..f0cf0744 100644 --- a/src/afb-session.c +++ b/src/afb-session.c @@ -33,10 +33,13 @@ #define SIZEUUID 37 #define HEADCOUNT 16 -#define COOKEYCOUNT 8 -#define COOKEYMASK (COOKEYCOUNT - 1) +#define COOKIECOUNT 8 +#define COOKIEMASK (COOKIECOUNT - 1) -#define NOW (time(NULL)) +#define _MAXEXP_ ((time_t)(~(time_t)0)) +#define _MAXEXP2_ ((time_t)((((unsigned long long)_MAXEXP_) >> 1))) +#define MAX_EXPIRATION (_MAXEXP_ >= 0 ? _MAXEXP_ : _MAXEXP2_) +#define NOW (time(NULL)) struct cookie { @@ -53,7 +56,8 @@ struct afb_session int timeout; time_t expiration; // expiration time of the token pthread_mutex_t mutex; - struct cookie *cookies[COOKEYCOUNT]; + struct cookie *cookies[COOKIECOUNT]; + char autoclose; char idx; char uuid[SIZEUUID]; // long term authentication of remote client char token[SIZEUUID]; // short term authentication of remote client @@ -94,7 +98,7 @@ static void close_session(struct afb_session *session) struct cookie *cookie; /* free cookies */ - for (idx = 0 ; idx < COOKEYCOUNT ; idx++) { + for (idx = 0 ; idx < COOKIECOUNT ; idx++) { while ((cookie = session->cookies[idx])) { session->cookies[idx] = cookie->next; if (cookie->freecb != NULL) @@ -120,8 +124,16 @@ static int pearson4(const char *text) return r; // % HEADCOUNT; } -// 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) +/** + * Initialize the session manager with a 'max_session_count', + * an initial common 'timeout' and an initial common token 'initok'. + * + * @param max_session_count maximum allowed session count in the same time + * @param timeout the initial default timeout of sessions + * @param initok the initial default token of sessions + * + */ +int afb_session_init (int max_session_count, int timeout, const char *initok) { pthread_mutex_init(&sessions.mutex, NULL); sessions.max = max_session_count; @@ -133,8 +145,10 @@ void afb_session_init (int max_session_count, int timeout, const char *initok) strcpy(sessions.initok, initok); else { ERROR("initial token '%s' too long (max length %d)", initok, ((int)(sizeof sessions.initok)) - 1); - exit(1); + errno = EINVAL; + return -1; } + return 0; } const char *afb_session_initial_token() @@ -175,20 +189,6 @@ static void destroy (struct afb_session *session) pthread_mutex_unlock(&sessions.mutex); } -// Check if context timeout or not -static int is_expired (struct afb_session *ctx, time_t now) -{ - assert (ctx != NULL); - return ctx->expiration < now; -} - -// Check if context is active or not -static int is_active (struct afb_session *ctx, time_t now) -{ - assert (ctx != NULL); - return ctx->uuid[0] != 0 && ctx->expiration >= now; -} - // Loop on every entry and remove old context sessions.hash static time_t cleanup () { @@ -202,7 +202,7 @@ static time_t cleanup () session = sessions.heads[idx]; while (session) { next = session->next; - if (is_expired(session, now)) + if (session->expiration < now) afb_session_close(session); session = next; } @@ -210,10 +210,35 @@ static time_t cleanup () return now; } +static void update_timeout(struct afb_session *session, time_t now, int timeout) +{ + time_t expiration; + + /* compute expiration */ + if (timeout == AFB_SESSION_TIMEOUT_INFINITE) + expiration = MAX_EXPIRATION; + else { + if (timeout == AFB_SESSION_TIMEOUT_DEFAULT) + expiration = now + sessions.timeout; + else + expiration = now + timeout; + if (expiration < 0) + expiration = MAX_EXPIRATION; + } + + /* record the values */ + session->timeout = timeout; + session->expiration = expiration; +} + +static void update_expiration(struct afb_session *session, time_t now) +{ + update_timeout(session, now, session->timeout); +} + static struct afb_session *add_session (const char *uuid, int timeout, time_t now, int idx) { struct afb_session *session; - time_t expiration; /* check arguments */ if (!AFB_SESSION_TIMEOUT_IS_VALID(timeout) @@ -228,16 +253,6 @@ static struct afb_session *add_session (const char *uuid, int timeout, time_t no return NULL; } - /* compute expiration */ - if (timeout == AFB_SESSION_TIMEOUT_DEFAULT) - timeout = sessions.timeout; - expiration = now + timeout; - if (timeout == AFB_SESSION_TIMEOUT_INFINITE || expiration < 0) { - expiration = (time_t)(~(time_t)0); - if (expiration < 0) - expiration = (time_t)(((unsigned long long)expiration) >> 1); - } - /* allocates a new one */ session = calloc(1, sizeof *session); if (session == NULL) { @@ -250,8 +265,7 @@ static struct afb_session *add_session (const char *uuid, int timeout, time_t no session->refcount = 1; strcpy(session->uuid, uuid); strcpy(session->token, sessions.initok); - session->timeout = timeout; - session->expiration = expiration; + update_timeout(session, now, timeout); /* link */ session->idx = (char)idx; @@ -355,7 +369,7 @@ void afb_session_unref(struct afb_session *session) assert(session->refcount != 0); if (!__atomic_sub_fetch(&session->refcount, 1, __ATOMIC_RELAXED)) { pthread_mutex_lock(&session->mutex); - if (session->uuid[0] == 0) + if (session->autoclose || session->uuid[0] == 0) destroy (session); else pthread_mutex_unlock(&session->mutex); @@ -363,7 +377,7 @@ void afb_session_unref(struct afb_session *session) } } -// Free Client Session Context +// close Client Session Context void afb_session_close (struct afb_session *session) { assert(session != NULL); @@ -380,14 +394,37 @@ void afb_session_close (struct afb_session *session) pthread_mutex_unlock(&session->mutex); } +/* set the autoclose flag */ +void afb_session_set_autoclose(struct afb_session *session, int autoclose) +{ + assert(session != NULL); + session->autoclose = (char)!!autoclose; +} + +// is the session active? +int afb_session_is_active (struct afb_session *session) +{ + assert(session != NULL); + return !!session->uuid[0]; +} + +// is the session closed? +int afb_session_is_closed (struct afb_session *session) +{ + assert(session != NULL); + return !session->uuid[0]; +} + // Sample Generic Ping Debug API int afb_session_check_token (struct afb_session *session, const char *token) { assert(session != NULL); assert(token != NULL); - // compare current token with previous one - if (!is_active (session, NOW)) + if (!session->uuid[0]) + return 0; + + if (session->expiration < NOW) return 0; if (session->token[0] && strcmp (token, session->token) != 0) @@ -405,8 +442,7 @@ void afb_session_new_token (struct afb_session *session) new_uuid(session->token); // keep track of time for session timeout and further clean up - if (session->timeout != 0) - session->expiration = NOW + session->timeout; + update_expiration(session, NOW); } /* Returns the uuid of 'session' */ @@ -432,7 +468,7 @@ static int cookeyidx(const void *key) { intptr_t x = (intptr_t)key; unsigned r = (unsigned)((x >> 5) ^ (x >> 15)); - return r & COOKEYMASK; + return r & COOKIEMASK; } /**