void (*free_value)(void*);
};
+struct cookie
+{
+ struct cookie *next;
+ const void *key;
+ void *value;
+ void (*free_value)(void*);
+};
+
struct AFB_clientCtx
{
unsigned refcount;
unsigned loa;
+ int timeout;
time_t expiration; // expiration time of the token
time_t access;
char uuid[37]; // long term authentication of remote client
char token[37]; // short term authentication of remote client
struct client_value *values;
+ struct cookie *cookies;
};
// Session UUID are store in a simple array [for 10 sessions this should be enough]
static void ctxUuidFreeCB (struct AFB_clientCtx *client)
{
int idx;
+ struct cookie *cookie;
// If application add a handle let's free it now
assert (client->values != NULL);
// Free client handle with a standard Free function, with app callback or ignore it
for (idx=0; idx < sessions.apicount; idx ++)
ctxClientValueSet(client, idx, NULL, NULL);
+
+ // free cookies
+ cookie = client->cookies;
+ while (cookie != NULL) {
+ client->cookies = cookie->next;
+ if (cookie->value != NULL && cookie->free_value != NULL)
+ cookie->free_value(cookie->value);
+ free(cookie);
+ cookie = client->cookies;
+ }
}
// Create a new store in RAM, not that is too small it will be automatically extended
/* init the token */
strcpy(clientCtx->token, sessions.initok);
- clientCtx->expiration = now + sessions.timeout;
+ clientCtx->timeout = timeout;
+ if (timeout != 0)
+ clientCtx->expiration = now + timeout;
+ else {
+ clientCtx->expiration = (time_t)(~(time_t)0);
+ if (clientCtx->expiration < 0)
+ clientCtx->expiration = (time_t)(((unsigned long long)clientCtx->expiration) >> 1);
+ }
if (!ctxStoreAdd (clientCtx)) {
errno = ENOMEM;
goto error2;
new_uuid(clientCtx->token);
// keep track of time for session timeout and further clean up
- clientCtx->expiration = NOW + sessions.timeout;
+ if (clientCtx->timeout != 0)
+ clientCtx->expiration = NOW + clientCtx->timeout;
}
const char *ctxClientGetUuid (struct AFB_clientCtx *clientCtx)
if (prev.value != NULL && prev.value != value && prev.free_value != NULL)
prev.free_value(prev.value);
}
+
+void *ctxClientCookieGet(struct AFB_clientCtx *clientCtx, const void *key)
+{
+ struct cookie *cookie;
+
+ cookie = clientCtx->cookies;
+ while(cookie != NULL) {
+ if (cookie->key == key)
+ return cookie->value;
+ cookie = cookie->next;
+ }
+ return NULL;
+}
+
+int ctxClientCookieSet(struct AFB_clientCtx *clientCtx, const void *key, void *value, void (*free_value)(void*))
+{
+ struct cookie *cookie;
+
+ /* search for a replacement */
+ cookie = clientCtx->cookies;
+ while(cookie != NULL) {
+ if (cookie->key == key) {
+ if (cookie->value != NULL && cookie->value != value && cookie->free_value != NULL)
+ cookie->free_value(cookie->value);
+ cookie->value = value;
+ cookie->free_value = free_value;
+ return 0;
+ }
+ cookie = cookie->next;
+ }
+
+ /* allocates */
+ cookie = malloc(sizeof *cookie);
+ if (cookie == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ cookie->key = key;
+ cookie->value = value;
+ cookie->free_value = free_value;
+ cookie->next = clientCtx->cookies;
+ clientCtx->cookies = cookie;
+ return 0;
+}
+