fundermental concurrency support for sessions

This commit is contained in:
overflowerror 2021-12-05 22:43:41 +01:00
parent e8a1c2dd46
commit 3d822269f8
6 changed files with 76 additions and 8 deletions

View file

@ -60,6 +60,7 @@ response_t sessions(ctx_t* ctx) {
if (*sessiondata == NULL) { if (*sessiondata == NULL) {
*sessiondata = "Test\n"; *sessiondata = "Test\n";
session_update(ctx);
} else { } else {
output = *sessiondata; output = *sessiondata;
} }

View file

@ -15,6 +15,8 @@
struct networkingConfig netConfig; struct networkingConfig netConfig;
void session_end(ctx_t*);
static void handler(struct request request, struct response _response) { static void handler(struct request request, struct response _response) {
ctx_t ctx = { ctx_t ctx = {
method: request.metaData.method, method: request.metaData.method,
@ -24,7 +26,8 @@ static void handler(struct request request, struct response _response) {
peerPort: request.peer.port, peerPort: request.peer.port,
auth: getAuthData(request.headers), auth: getAuthData(request.headers),
requestHeaders: *request.headers, requestHeaders: *request.headers,
responseHeaders: headers_create() responseHeaders: headers_create(),
session: EMPTY_SESSION_CTX,
}; };
response_t response = routerHandler(&ctx); response_t response = routerHandler(&ctx);
@ -33,6 +36,7 @@ static void handler(struct request request, struct response _response) {
} }
freeAuthData(ctx.auth); freeAuthData(ctx.auth);
session_end(&ctx);
headers_merge(&ctx.responseHeaders, &response.headers); headers_merge(&ctx.responseHeaders, &response.headers);

View file

@ -96,6 +96,8 @@ const char* or(const char* v1, const char* v2) {
} }
} }
void session_end(ctx_t*);
int main(int argc, char** argv) { int main(int argc, char** argv) {
struct headers headers = headers_create(); struct headers headers = headers_create();
if (setHttpHeaders(&headers)) { if (setHttpHeaders(&headers)) {
@ -111,7 +113,8 @@ int main(int argc, char** argv) {
peerPort: 0, // TODO peerPort: 0, // TODO
auth: getAuthData(request.headers), auth: getAuthData(request.headers),
requestHeaders: headers, requestHeaders: headers,
responseHeaders: headers_create() responseHeaders: headers_create(),
session: EMPTY_SESSION_CTX,
}; };
response_t response = routerHandler(&ctx); response_t response = routerHandler(&ctx);
@ -124,6 +127,7 @@ int main(int argc, char** argv) {
headers_merge(&ctx.responseHeaders, &response.headers); headers_merge(&ctx.responseHeaders, &response.headers);
freeAuthData(ctx.auth); freeAuthData(ctx.auth);
session_end(&ctx);
printf("Status: %d\n\r", response.status); printf("Status: %d\n\r", response.status);
headers_dump(&ctx.responseHeaders, stdout); headers_dump(&ctx.responseHeaders, stdout);

View file

@ -11,6 +11,14 @@
#define NEXT_RESPONSE_STATUS (0) #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 { typedef struct {
method_t method; method_t method;
const char* path; const char* path;
@ -20,6 +28,7 @@ typedef struct {
struct auth auth; struct auth auth;
struct headers requestHeaders; struct headers requestHeaders;
struct headers responseHeaders; struct headers responseHeaders;
struct session_ctx session;
} ctx_t; } ctx_t;
typedef struct { typedef struct {

View file

@ -1,10 +1,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdbool.h> #include <stdbool.h>
#include <time.h>
#include <string.h> #include <string.h>
#include <uuid/uuid.h>
#include <pthread.h> #include <pthread.h>
#include <headers.h> #include <headers.h>
@ -15,12 +12,15 @@
#include "cookies.h" #include "cookies.h"
static struct session { struct session {
bool inUse; bool inUse;
uuid_t id; uuid_t id;
time_t lastAccess; time_t lastAccess;
time_t lastWrite;
void* data; void* data;
}* sessions = NULL; };
static struct session* sessions = NULL;
static size_t sessionno = 0; static size_t sessionno = 0;
static pthread_mutex_t globalLock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t globalLock = PTHREAD_MUTEX_INITIALIZER;
@ -51,6 +51,7 @@ struct session* newSession(size_t size) {
return NULL; return NULL;
} }
memset(sessions[i].data, 0, size); memset(sessions[i].data, 0, size);
sessions[i].lastWrite = 0;
return &(sessions[i]); return &(sessions[i]);
} }
} }
@ -116,6 +117,45 @@ void* _session_start(ctx_t* ctx, const char* cookie, size_t size) {
pthread_mutex_unlock(&globalLock); pthread_mutex_unlock(&globalLock);
session->lastAccess = time(NULL); 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);
}
} }

View file

@ -1,6 +1,10 @@
#ifndef SESSIONS_H_ #ifndef SESSIONS_H_
#define SESSIONS_H_ #define SESSIONS_H_
#include <time.h>
#include <uuid/uuid.h>
#ifndef SESSION_PTR_TYPE #ifndef SESSION_PTR_TYPE
#pragma GCC warning "session ptr type not defined" #pragma GCC warning "session ptr type not defined"
#define SESSION_PTR_TYPE int #define SESSION_PTR_TYPE int
@ -16,8 +20,14 @@
#include "request.h" #include "request.h"
#define ERROR_NO_SESSION (-2)
#define ERROR_CONCURRENT_SESSION (-1)
void* _session_start(ctx_t*, const char*, size_t); 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_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 #endif