Csilk 0.2.1
A lightweight, high-performance C HTTP web framework
Loading...
Searching...
No Matches
session.c File Reference

Cookie-based session management middleware with thread-safe protection. More...

#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <uv.h>
#include "csilk/core/internal.h"
#include "csilk/csilk.h"
Include dependency graph for session.c:

Data Structures

struct  csilk_session_data_t
 Session data item (key-value pair). More...
 
struct  csilk_session_t
 Session structure. More...
 

Macros

#define SESSION_COOKIE   "csilk_session"
 Session cookie name.
 
#define SESSION_TTL   3600
 Default session TTL (seconds).
 

Functions

static void init_session_mutex (void)
 Initialize the session store mutex (called once via uv_once).
 
static void session_lock (void)
 Lock the session store mutex.
 
static void session_unlock (void)
 Unlock the session store mutex.
 
static void generate_session_id (csilk_ctx_t *c, char id[37])
 Generate a cryptographically random session ID.
 
static csilk_session_tfind_session (const char *id)
 Find a session by ID in the global store.
 
static csilk_session_tfind_session_locked (const char *id)
 Find a session by ID (acquires and releases the mutex).
 
static void add_session_locked (csilk_session_t *session)
 Add a session to the store (acquires and releases the mutex).
 
static void remove_session_locked (csilk_session_t *session)
 Remove a session from the store (acquires and releases the mutex).
 
static void cleanup_expired (void)
 Remove expired sessions from the global store.
 
void csilk_session_init (void)
 Initialize the session system.
 
void csilk_session_start (csilk_ctx_t *c)
 Start or resume a session for the current request.
 
void csilk_session_set (csilk_ctx_t *c, const char *key, void *value)
 Store a value in the session.
 
void * csilk_session_get (csilk_ctx_t *c, const char *key)
 Retrieve a value from the session.
 
void csilk_session_destroy (csilk_ctx_t *c)
 Destroy the current session.
 

Variables

static csilk_session_tsession_store = NULL
 Global session store (singly-linked list of active sessions).
 
static uv_mutex_t session_mutex
 Session store mutex — guards session_store and all linked-list operations against concurrent access.
 
static uv_once_t session_mutex_once = UV_ONCE_INIT
 One-time initialization guard for session_mutex.
 

Detailed Description

Cookie-based session management middleware with thread-safe protection.


Data Structure Documentation

◆ csilk_session_data_t

struct csilk_session_data_t

Session data item (key-value pair).

Each session contains a singly-linked list of these items, each holding a string key and an opaque void* value.

Data Fields
char * key
struct csilk_session_data_s * next
void * value

◆ csilk_session_t

struct csilk_session_t

Session structure.

Represents an individual session with a UUID-based ID, an expiry timestamp, a linked list of key-value data items, and a pointer to the next session in the global store (singly-linked list).

Collaboration diagram for csilk_session_t:
Data Fields
csilk_session_data_t * data
time_t expires_at
char id[37]
struct csilk_session_s * next

Macro Definition Documentation

◆ SESSION_COOKIE

#define SESSION_COOKIE   "csilk_session"

Session cookie name.

◆ SESSION_TTL

#define SESSION_TTL   3600

Default session TTL (seconds).

Function Documentation

◆ add_session_locked()

static void add_session_locked ( csilk_session_t session)
static

Add a session to the store (acquires and releases the mutex).

Prepends the session to the global singly-linked list of active sessions.

Parameters
sessionThe session to add. Must not be NULL.

◆ cleanup_expired()

static void cleanup_expired ( void  )
static

Remove expired sessions from the global store.

Iterates over the session list and removes (frees) every session whose expires_at timestamp is <= the current time. Also frees all key-value data items belonging to each expired session.

Note
Acquires and releases session_mutex during the sweep.

◆ csilk_session_destroy()

void csilk_session_destroy ( csilk_ctx_t *  c)

Destroy the current session.

Destroy the session and clear the session cookie.

Removes the session from the global store, frees all its key-value data items and the session struct itself, clears the "_session" context entry, and sets an empty session cookie with a negative max-age to instruct the client to delete it.

Parameters
cThe request context.

◆ csilk_session_get()

void * csilk_session_get ( csilk_ctx_t *  c,
const char *  key 
)

Retrieve a value from the session.

Searches the current session's data list for the given key and returns its associated value.

Parameters
cThe request context (used to look up the session).
keyNull-terminated key string. Must not be NULL.
Returns
The value pointer previously stored with csilk_session_set(), or NULL if the key is not found or no session is active.

◆ csilk_session_init()

void csilk_session_init ( void  )

Initialize the session system.

Initialise the session subsystem (call once at startup).

Performs an immediate cleanup of any expired sessions from the store. This should be called once during server startup.

◆ csilk_session_set()

void csilk_session_set ( csilk_ctx_t *  c,
const char *  key,
void *  value 
)

Store a value in the session.

If the key already exists in the current session, its value is replaced. Otherwise, a new key-value pair is prepended to the session's data list.

Parameters
cThe request context (used to look up the session via csilk_get(c, "_session")).
keyNull-terminated key string. Must not be NULL.
valueOpaque pointer to the value to store. May be NULL.
Note
The key is duplicated via strdup(). The value pointer is stored as-is — the caller is responsible for managing its lifetime.
Warning
This function does NOT acquire the session mutex. It operates on the session pointer stored in the per-request context, which is already exclusively owned by the current request handler.

◆ csilk_session_start()

void csilk_session_start ( csilk_ctx_t *  c)

Start or resume a session for the current request.

Looks for an existing session cookie named "csilk_session". If a valid session is found, its expiry is extended by SESSION_TTL seconds. If not, a new session is created with a fresh UUID, stored in the global list, and a session cookie is set on the response. The session pointer is stored in the context under the key "_session".

Parameters
cThe request context.
Note
Must be called after csilk_request_id_middleware (or equivalent) so that _csilk_generate_uuid is available.
Warning
The session's data items are NOT automatically serialized to persistent storage. All sessions are in-memory and are lost on process restart.

◆ find_session()

static csilk_session_t * find_session ( const char *  id)
static

Find a session by ID in the global store.

Performs a linear search of the singly-linked session list.

Parameters
idThe session ID string to search for.
Returns
Pointer to the csilk_session_t if found, NULL otherwise.
Note
This function does NOT acquire the mutex. The caller must hold session_mutex when calling this function.

◆ find_session_locked()

static csilk_session_t * find_session_locked ( const char *  id)
static

Find a session by ID (acquires and releases the mutex).

Convenience wrapper around find_session() that handles locking for single-lookup callers.

Parameters
idThe session ID string to search for.
Returns
Pointer to the csilk_session_t if found, NULL otherwise.

◆ generate_session_id()

static void generate_session_id ( csilk_ctx_t *  c,
char  id[37] 
)
static

Generate a cryptographically random session ID.

Delegates to _csilk_generate_uuid() to produce a UUID v4 string and writes it into the provided 37-character buffer.

Parameters
cThe request context.
idOutput buffer of at least 37 bytes to receive the null-terminated UUID string.

◆ init_session_mutex()

static void init_session_mutex ( void  )
static

Initialize the session store mutex (called once via uv_once).

◆ remove_session_locked()

static void remove_session_locked ( csilk_session_t session)
static

Remove a session from the store (acquires and releases the mutex).

Unlinks the session from the global singly-linked list of active sessions. Does NOT free the session or its data — the caller must do that after removal.

Parameters
sessionThe session to remove. Must be a valid pointer currently in the store.

◆ session_lock()

static void session_lock ( void  )
static

Lock the session store mutex.

Ensures the mutex is initialized (via uv_once) before acquiring the lock. Blocks until the lock is held.

◆ session_unlock()

static void session_unlock ( void  )
static

Unlock the session store mutex.

Releases the lock previously acquired by session_lock().

Variable Documentation

◆ session_mutex

uv_mutex_t session_mutex
static

Session store mutex — guards session_store and all linked-list operations against concurrent access.

◆ session_mutex_once

uv_once_t session_mutex_once = UV_ONCE_INIT
static

One-time initialization guard for session_mutex.

Ensures uv_mutex_init is called exactly once across all threads, regardless of which thread triggers the first session operation.

◆ session_store

csilk_session_t* session_store = NULL
static

Global session store (singly-linked list of active sessions).

Protected by a libuv mutex. All read/write access to this pointer must occur while session_mutex is held. The linked-list design is chosen over a hash table for simplicity; with typical concurrency levels the O(n) traversal is acceptable for <10K active sessions.