Also, improve readability and memory footprint
Bug-AGL: SPEC-2968
Change-Id: I90104fb19a44e2810b92bef51d774acf734fd90f
Signed-off-by: Jose Bollo <jose.bollo@iot.bzh>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
-#include "afb-session.h"
#include "verbose.h"
#include "afb-api.h"
#include "afb-apiset.h"
#include "verbose.h"
#include "afb-api.h"
#include "afb-apiset.h"
#include "pearson.h"
#include "uuid.h"
#include "pearson.h"
#include "uuid.h"
+#define SESSION_COUNT_MIN 5
+#define SESSION_COUNT_MAX 1000
+
+/*
+ * Handling of cookies.
+ * Cookies are stored by session.
+ * The cookie count COOKIECOUNT must be a power of 2, possible values: 1, 2, 4, 8, 16, 32, 64, ...
+ * For low memory profile, small values are better, 1 is possible.
+ */
#define COOKIECOUNT 8
#define COOKIEMASK (COOKIECOUNT - 1)
#define COOKIECOUNT 8
#define COOKIEMASK (COOKIECOUNT - 1)
struct afb_session
{
struct afb_session *next; /**< link to the next */
struct afb_session
{
struct afb_session *next; /**< link to the next */
- unsigned refcount; /**< count of reference to the session */
+ uint16_t refcount; /**< count of reference to the session */
+ uint16_t id; /**< local id of the session */
int timeout; /**< timeout of the session */
time_t expiration; /**< expiration time of the session */
pthread_mutex_t mutex; /**< mutex of the session */
int timeout; /**< timeout of the session */
time_t expiration; /**< expiration time of the session */
pthread_mutex_t mutex; /**< mutex of the session */
uint8_t closed: 1; /**< is the session closed ? */
uint8_t autoclose: 1; /**< close the session when unreferenced */
uint8_t notinset: 1; /**< session removed from the set of sessions */
uint8_t closed: 1; /**< is the session closed ? */
uint8_t autoclose: 1; /**< close the session when unreferenced */
uint8_t notinset: 1; /**< session removed from the set of sessions */
- uuid_stringz_t uuid; /**< indentification of client seesion */
+ uint8_t hash; /**< hash value of the uuid */
+ uuid_stringz_t uuid; /**< identification of client session */
};
/**
* structure for managing sessions
*/
static struct {
};
/**
* structure for managing sessions
*/
static struct {
- int count; /**< current number of sessions */
- int max; /**< maximum count of sessions */
- int timeout; /**< common initial timeout */
- struct afb_session *heads[HEADCOUNT]; /**< sessions */
+ uint16_t count; /**< current number of sessions */
+ uint16_t max; /**< maximum count of sessions */
+ uint16_t genid; /**< for generating ids */
+ int timeout; /**< common initial timeout */
+ struct afb_session *first; /**< sessions */
struct afb_token *initok;/**< common initial token */
struct afb_token *initok;/**< common initial token */
- pthread_mutex_t mutex; /**< declare a mutex to protect hash table */
+ pthread_mutex_t mutex; /**< declare a mutex to protect hash table */
} sessions = {
.count = 0,
.max = 10,
} sessions = {
.count = 0,
.max = 10,
.initok = 0,
.mutex = PTHREAD_MUTEX_INITIALIZER
};
.initok = 0,
.mutex = PTHREAD_MUTEX_INITIALIZER
};
{
struct afb_session *session;
{
struct afb_session *session;
- session = sessions.heads[hashidx];
- while (session && strcmp(uuid, session->uuid))
+ session = sessions.first;
+ while (session && hashidx != session->hash && strcmp(uuid, session->uuid))
+ session = session->next;
+
+ return session;
+}
+
+/*
+ * search within the set of sessions the session of 'id'.
+ * return the session or NULL
+ */
+static struct afb_session *sessionset_search_id(uint16_t id)
+{
+ struct afb_session *session;
+
+ session = sessions.first;
+ while (session && id != session->id)
session = session->next;
return session;
session = session->next;
return session;
- session->next = sessions.heads[hashidx];
- sessions.heads[hashidx] = session;
+ session->next = sessions.first;
+ sessions.first = session;
sessions.count++;
return 0;
}
sessions.count++;
return 0;
}
strcpy(session->uuid, uuid);
session->timeout = timeout;
session_update_expiration(session, now);
strcpy(session->uuid, uuid);
session->timeout = timeout;
session_update_expiration(session, now);
+ session->id = ++sessions.genid;
+ while (session->id == 0 || sessionset_search_id(session->id) != NULL)
+ session->id = ++sessions.genid;
/* add */
if (sessionset_add(session, hashidx)) {
/* add */
if (sessionset_add(session, hashidx)) {
static time_t sessionset_cleanup (int force)
{
struct afb_session *session, **prv;
static time_t sessionset_cleanup (int force)
{
struct afb_session *session, **prv;
time_t now;
/* Loop on Sessions Table and remove anything that is older than timeout */
now = NOW;
time_t now;
/* Loop on Sessions Table and remove anything that is older than timeout */
now = NOW;
- for (idx = 0 ; idx < HEADCOUNT; idx++) {
- prv = &sessions.heads[idx];
- while ((session = *prv)) {
- session_lock(session);
- if (force || session->expiration < now)
- session_close(session);
- if (!session->closed)
- prv = &session->next;
- else {
- *prv = session->next;
- sessions.count--;
- session->notinset = 1;
- if ( !session->refcount) {
- session_destroy(session);
- continue;
- }
- }
+ prv = &sessions.first;
+ while ((session = *prv)) {
+ session_lock(session);
+ if (force || session->expiration < now)
+ session_close(session);
+ if (!session->closed) {
+ prv = &session->next;
+ } else {
+ *prv = session->next;
+ sessions.count--;
+ session->notinset = 1;
+ if (session->refcount)
+ session_unlock(session);
+ else
+ session_destroy(session);
/* init the sessionset (after cleanup) */
sessionset_lock();
sessionset_cleanup(1);
/* init the sessionset (after cleanup) */
sessionset_lock();
sessionset_cleanup(1);
- sessions.max = max_session_count;
+ if (max_session_count > SESSION_COUNT_MAX)
+ sessions.max = SESSION_COUNT_MAX;
+ else if (max_session_count < SESSION_COUNT_MIN)
+ sessions.max = SESSION_COUNT_MIN;
+ else
+ sessions.max = (uint16_t)max_session_count;
sessions.timeout = timeout;
if (initok == NULL) {
uuid_new_stringz(uuid);
sessions.timeout = timeout;
if (initok == NULL) {
uuid_new_stringz(uuid);
void afb_session_foreach(void (*callback)(void *closure, struct afb_session *session), void *closure)
{
struct afb_session *session;
void afb_session_foreach(void (*callback)(void *closure, struct afb_session *session), void *closure)
{
struct afb_session *session;
/* Loop on Sessions Table and remove anything that is older than timeout */
sessionset_lock();
/* Loop on Sessions Table and remove anything that is older than timeout */
sessionset_lock();
- for (idx = 0 ; idx < HEADCOUNT; idx++) {
- session = sessions.heads[idx];
- while (session) {
- if (!session->closed)
- callback(closure, session);
- session = session->next;
- }
+ session = sessions.first;
+ while (session) {
+ if (!session->closed)
+ callback(closure, session);
+ session = session->next;
*/
int afb_session_what_remains(struct afb_session *session)
{
*/
int afb_session_what_remains(struct afb_session *session)
{
- return (int)(session->expiration - NOW);
+ int diff = (int)(session->expiration - NOW);
+ return diff < 0 ? 0 : diff;
}
/* This function will return exiting session or newly created session */
}
/* This function will return exiting session or newly created session */
+/* Returns the local id of 'session' */
+uint16_t afb_session_id (struct afb_session *session)
+{
+ return session->id;
+}
+
/**
* 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
*/
/**
* 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 & COOKIEMASK;
}
static int cookeyidx(const void *key)
{
intptr_t x = (intptr_t)key;
unsigned r = (unsigned)((x >> 5) ^ (x >> 15));
return r & COOKIEMASK;
}
+#else
+# define cookeyidx(key) 0
+#endif
/**
* Set, get, replace, remove a cookie of 'key' for the 'session'
/**
* Set, get, replace, remove a cookie of 'key' for the 'session'
extern struct afb_session *afb_session_search (const char *uuid);
extern struct afb_session *afb_session_get (const char *uuid, int timeout, int *created);
extern const char *afb_session_uuid (struct afb_session *session);
extern struct afb_session *afb_session_search (const char *uuid);
extern struct afb_session *afb_session_get (const char *uuid, int timeout, int *created);
extern const char *afb_session_uuid (struct afb_session *session);
+extern uint16_t afb_session_id (struct afb_session *session);
extern struct afb_session *afb_session_addref(struct afb_session *session);
extern void afb_session_unref(struct afb_session *session);
extern struct afb_session *afb_session_addref(struct afb_session *session);
extern void afb_session_unref(struct afb_session *session);