From 3d822269f860e637bb2cedd8535c11d0de27b9a2 Mon Sep 17 00:00:00 2001 From: overflowerror Date: Sun, 5 Dec 2021 22:43:41 +0100 Subject: [PATCH] fundermental concurrency support for sessions --- demo/demo.c | 1 + src/base_cfloor.c | 6 +++++- src/base_cgi.c | 6 +++++- src/request.h | 9 ++++++++ src/sessions.c | 52 +++++++++++++++++++++++++++++++++++++++++------ src/sessions.h | 10 +++++++++ 6 files changed, 76 insertions(+), 8 deletions(-) diff --git a/demo/demo.c b/demo/demo.c index e2eb4c7..bae50e7 100644 --- a/demo/demo.c +++ b/demo/demo.c @@ -60,6 +60,7 @@ response_t sessions(ctx_t* ctx) { if (*sessiondata == NULL) { *sessiondata = "Test\n"; + session_update(ctx); } else { output = *sessiondata; } diff --git a/src/base_cfloor.c b/src/base_cfloor.c index e3800d8..d6bd49c 100644 --- a/src/base_cfloor.c +++ b/src/base_cfloor.c @@ -15,6 +15,8 @@ struct networkingConfig netConfig; +void session_end(ctx_t*); + static void handler(struct request request, struct response _response) { ctx_t ctx = { method: request.metaData.method, @@ -24,7 +26,8 @@ static void handler(struct request request, struct response _response) { peerPort: request.peer.port, auth: getAuthData(request.headers), requestHeaders: *request.headers, - responseHeaders: headers_create() + responseHeaders: headers_create(), + session: EMPTY_SESSION_CTX, }; response_t response = routerHandler(&ctx); @@ -33,6 +36,7 @@ static void handler(struct request request, struct response _response) { } freeAuthData(ctx.auth); + session_end(&ctx); headers_merge(&ctx.responseHeaders, &response.headers); diff --git a/src/base_cgi.c b/src/base_cgi.c index abc7d31..6fdcf08 100644 --- a/src/base_cgi.c +++ b/src/base_cgi.c @@ -96,6 +96,8 @@ const char* or(const char* v1, const char* v2) { } } +void session_end(ctx_t*); + int main(int argc, char** argv) { struct headers headers = headers_create(); if (setHttpHeaders(&headers)) { @@ -111,7 +113,8 @@ int main(int argc, char** argv) { peerPort: 0, // TODO auth: getAuthData(request.headers), requestHeaders: headers, - responseHeaders: headers_create() + responseHeaders: headers_create(), + session: EMPTY_SESSION_CTX, }; response_t response = routerHandler(&ctx); @@ -124,6 +127,7 @@ int main(int argc, char** argv) { headers_merge(&ctx.responseHeaders, &response.headers); freeAuthData(ctx.auth); + session_end(&ctx); printf("Status: %d\n\r", response.status); headers_dump(&ctx.responseHeaders, stdout); diff --git a/src/request.h b/src/request.h index df7c24e..6099a5d 100644 --- a/src/request.h +++ b/src/request.h @@ -11,6 +11,14 @@ #define NEXT_RESPONSE_STATUS (0) +struct session_ctx { + void* session; + time_t accessTime; + void* data; +}; + +#define EMPTY_SESSION_CTX ((struct session_ctx) {.session = NULL}) + typedef struct { method_t method; const char* path; @@ -20,6 +28,7 @@ typedef struct { struct auth auth; struct headers requestHeaders; struct headers responseHeaders; + struct session_ctx session; } ctx_t; typedef struct { diff --git a/src/sessions.c b/src/sessions.c index 896911f..c5be62d 100644 --- a/src/sessions.c +++ b/src/sessions.c @@ -1,10 +1,7 @@ #include #include -#include #include -#include - #include #include @@ -15,12 +12,15 @@ #include "cookies.h" -static struct session { +struct session { bool inUse; uuid_t id; time_t lastAccess; + time_t lastWrite; void* data; -}* sessions = NULL; +}; + +static struct session* sessions = NULL; static size_t sessionno = 0; static pthread_mutex_t globalLock = PTHREAD_MUTEX_INITIALIZER; @@ -51,6 +51,7 @@ struct session* newSession(size_t size) { return NULL; } memset(sessions[i].data, 0, size); + sessions[i].lastWrite = 0; return &(sessions[i]); } } @@ -116,6 +117,45 @@ void* _session_start(ctx_t* ctx, const char* cookie, size_t size) { pthread_mutex_unlock(&globalLock); session->lastAccess = time(NULL); + + ctx->session.session = session; + ctx->session.accessTime = time(NULL); + + void* requestSessionData = malloc(size); + if (requestSessionData == NULL) { + return NULL; + } + memcpy(requestSessionData, session->data, size); + ctx->session.data = requestSessionData; - return session->data; + return requestSessionData; +} + +int _session_update(ctx_t* ctx, size_t size) { + struct session_ctx* sessionCtx = &(ctx->session); + struct session* session = (struct session*) sessionCtx->session; + if (session == NULL) { + return ERROR_NO_SESSION; + } + + pthread_mutex_lock(&globalLock); + + if (session->lastWrite > sessionCtx->accessTime) { + pthread_mutex_unlock(&globalLock); + return ERROR_CONCURRENT_SESSION; + } + + session->lastWrite = time(NULL); + sessionCtx->accessTime = session->lastWrite; + memcpy(session->data, sessionCtx->data, size); + + pthread_mutex_unlock(&globalLock); + + return 0; +} + +void session_end(ctx_t* ctx) { + if (ctx->session.session != NULL) { + free(ctx->session.data); + } } diff --git a/src/sessions.h b/src/sessions.h index bde7f16..f7a41ae 100644 --- a/src/sessions.h +++ b/src/sessions.h @@ -1,6 +1,10 @@ #ifndef SESSIONS_H_ #define SESSIONS_H_ +#include + +#include + #ifndef SESSION_PTR_TYPE #pragma GCC warning "session ptr type not defined" #define SESSION_PTR_TYPE int @@ -16,8 +20,14 @@ #include "request.h" +#define ERROR_NO_SESSION (-2) +#define ERROR_CONCURRENT_SESSION (-1) + void* _session_start(ctx_t*, const char*, size_t); +int _session_update(ctx_t*, size_t); +void session_end(ctx_t*); #define session_start(c) ((SESSION_PTR_TYPE*) _session_start(c, SESSION_COOKIE_NAME, sizeof(SESSION_PTR_TYPE))) +#define session_update(c) _session_update(c, sizeof(SESSION_PTR_TYPE)) #endif