From b3d911685eef70d5200e17284a534cfadc4ebb09 Mon Sep 17 00:00:00 2001 From: SimonFJ20 Date: Fri, 14 Mar 2025 09:16:50 +0100 Subject: [PATCH] cx thread safe --- backend/src/controllers/carts.c | 7 -- backend/src/controllers/controllers.h | 13 ++-- backend/src/controllers/cx.c | 95 +++++++++++++++++++++++++++ backend/src/controllers/sessions.c | 59 ++--------------- backend/src/db/db.h | 3 - backend/src/db/db_sqlite.c | 41 ------------ backend/src/main.c | 8 +-- 7 files changed, 111 insertions(+), 115 deletions(-) create mode 100644 backend/src/controllers/cx.c diff --git a/backend/src/controllers/carts.c b/backend/src/controllers/carts.c index 648a59d..fff5f69 100644 --- a/backend/src/controllers/carts.c +++ b/backend/src/controllers/carts.c @@ -12,13 +12,6 @@ void route_get_cart_items_from_session(HttpCtx* ctx) CartItemVec cart_items; cart_item_vec_construct(&cart_items); - DbRes db_res - = db_cart_items_with_user_id(cx->db, &cart_items, session->user_id); - if (db_res != DbRes_Ok) { - RESPOND_BAD_REQUEST(ctx, "Could not find cart for user"); - return; - } - String res; string_construct(&res); diff --git a/backend/src/controllers/controllers.h b/backend/src/controllers/controllers.h index 0716e55..3df36cd 100644 --- a/backend/src/controllers/controllers.h +++ b/backend/src/controllers/controllers.h @@ -2,6 +2,7 @@ #include "../db/db.h" #include "../http/http.h" +#include #include #include @@ -16,16 +17,20 @@ void session_destroy(Session* session); DEFINE_VEC(Session, SessionVec, session_vec, 16) -void sessions_remove(SessionVec* vec, int64_t user_id); -Session* sessions_add(SessionVec* vec, int64_t user_id); -const Session* sessions_find(SessionVec* vec, const char* token); - typedef struct { + pthread_mutex_t mutex; int number; SessionVec sessions; Db* db; } Cx; +void cx_construct(Cx* cx, Db* db); +void cx_destroy(Cx* cx); + +void cx_sessions_remove(Cx* cx, int64_t user_id); +Session* cx_sessions_add(Cx* cx, int64_t user_id); +const Session* cx_sessions_find(Cx* cx, const char* token); + void route_get_index(HttpCtx* ctx); void route_post_set_number(HttpCtx* ctx); void route_get_not_found(HttpCtx* ctx); diff --git a/backend/src/controllers/cx.c b/backend/src/controllers/cx.c new file mode 100644 index 0000000..fee0e78 --- /dev/null +++ b/backend/src/controllers/cx.c @@ -0,0 +1,95 @@ +#include "../util/str.h" +#include "controllers.h" +#include + +void session_construct(Session* session, int64_t user_id) +{ + char* token = str_random(64); + size_t token_hash = str_fast_hash(token); + *session = (Session) { user_id, token, token_hash }; +} + +void session_destroy(Session* session) +{ + free(session->token); + *session = (Session) { + .user_id = 0, + .token = NULL, + .token_hash = 0, + }; +} + +void cx_construct(Cx* cx, Db* db) +{ + *cx = (Cx) { + .mutex = PTHREAD_MUTEX_INITIALIZER, + .number = 1, + .sessions = (SessionVec) { 0 }, + .db = db, + }; + session_vec_construct(&cx->sessions); +} + +void cx_destroy(Cx* cx) +{ + pthread_mutex_destroy(&cx->mutex); + session_vec_destroy(&cx->sessions); +} + +void cx_sessions_remove(Cx* cx, int64_t user_id) +{ + pthread_mutex_lock(&cx->mutex); + + SessionVec* vec = &cx->sessions; + for (size_t i = 0; i < vec->size; ++i) { + if (vec->data[i].user_id == user_id) { + session_destroy(&vec->data[i]); + } + } + + pthread_mutex_unlock(&cx->mutex); +} + +Session* cx_sessions_add(Cx* cx, int64_t user_id) +{ + Session* res; + pthread_mutex_lock(&cx->mutex); + + SessionVec* vec = &cx->sessions; + for (size_t i = 0; i < vec->size; ++i) { + if (vec->data[i].user_id == 0) { + session_construct(&vec->data[i], user_id); + res = &vec->data[i]; + goto l0_return; + } + } + Session session; + session_construct(&session, user_id); + session_vec_push(vec, session); + + res = &vec->data[vec->size - 1]; + +l0_return: + pthread_mutex_unlock(&cx->mutex); + return res; +} + +const Session* cx_sessions_find(Cx* cx, const char* token) +{ + const Session* res; + pthread_mutex_lock(&cx->mutex); + + SessionVec* vec = &cx->sessions; + size_t token_hash = str_fast_hash(token); + for (size_t i = 0; i < vec->size; ++i) { + if (vec->data[i].token_hash == token_hash) { + res = &vec->data[i]; + goto l0_return; + } + } + res = NULL; + +l0_return: + pthread_mutex_unlock(&cx->mutex); + return res; +} diff --git a/backend/src/controllers/sessions.c b/backend/src/controllers/sessions.c index f3ddbdb..224ca9f 100644 --- a/backend/src/controllers/sessions.c +++ b/backend/src/controllers/sessions.c @@ -41,8 +41,8 @@ void route_post_sessions_login(HttpCtx* ctx) goto l2_return; } - sessions_remove(&cx->sessions, user.id); - Session* session = sessions_add(&cx->sessions, user.id); + cx_sessions_remove(cx, user.id); + Session* session = cx_sessions_add(cx, user.id); RESPOND_JSON(ctx, 200, "{\"ok\":true,\"token\":\"%s\"}", session->token); l2_return: @@ -59,7 +59,7 @@ void route_post_sessions_logout(HttpCtx* ctx) RESPOND_JSON(ctx, 200, "{\"ok\":true}"); return; } - sessions_remove(&cx->sessions, session->user_id); + cx_sessions_remove(cx, session->user_id); RESPOND_JSON(ctx, 200, "{\"ok\":true}"); } @@ -92,7 +92,7 @@ const Session* header_session(HttpCtx* ctx) } const char* token = http_ctx_req_headers_get(ctx, "Session-Token"); // session expiration should be handled here - return sessions_find(&cx->sessions, token); + return cx_sessions_find(cx, token); } // Returns NULL AND responds if no valid session is found. @@ -105,54 +105,3 @@ const Session* middleware_session(HttpCtx* ctx) } return session; } - -void session_construct(Session* session, int64_t user_id) -{ - char* token = str_random(64); - size_t token_hash = str_fast_hash(token); - *session = (Session) { user_id, token, token_hash }; -} - -void session_destroy(Session* session) -{ - free(session->token); - *session = (Session) { - .user_id = 0, - .token = NULL, - .token_hash = 0, - }; -} - -void sessions_remove(SessionVec* vec, int64_t user_id) -{ - for (size_t i = 0; i < vec->size; ++i) { - if (vec->data[i].user_id == user_id) { - session_destroy(&vec->data[i]); - } - } -} - -Session* sessions_add(SessionVec* vec, int64_t user_id) -{ - for (size_t i = 0; i < vec->size; ++i) { - if (vec->data[i].user_id == 0) { - session_construct(&vec->data[i], user_id); - return &vec->data[i]; - } - } - Session session; - session_construct(&session, user_id); - session_vec_push(vec, session); - return &vec->data[vec->size - 1]; -} - -const Session* sessions_find(SessionVec* vec, const char* token) -{ - size_t token_hash = str_fast_hash(token); - for (size_t i = 0; i < vec->size; ++i) { - if (vec->data[i].token_hash == token_hash) { - return &vec->data[i]; - } - } - return NULL; -} diff --git a/backend/src/db/db.h b/backend/src/db/db.h index cadd373..1646fea 100644 --- a/backend/src/db/db.h +++ b/backend/src/db/db.h @@ -29,6 +29,3 @@ DbRes db_user_with_email(Db* db, User* user, const char* email); /// Expects `vec` to be constructed. DbRes db_product_all(Db* db, ProductVec* vec); - -__attribute__((deprecated("store in memory instead"))) DbRes -db_cart_items_with_user_id(Db* db, CartItemVec* vec, int64_t user_id); diff --git a/backend/src/db/db_sqlite.c b/backend/src/db/db_sqlite.c index 41383c0..f1affc3 100644 --- a/backend/src/db/db_sqlite.c +++ b/backend/src/db/db_sqlite.c @@ -279,44 +279,3 @@ l0_return: DISCONNECT; return res; } - -DbRes db_cart_items_with_user_id(Db* db, CartItemVec* vec, int64_t user_id) -{ - static_assert(sizeof(CartItem) == 32, "model has changed"); - - sqlite3* connection; - CONNECT; - DbRes res; - - sqlite3_stmt* stmt; - int sqlite_res; - - sqlite_res = sqlite3_prepare_v2(connection, - "SELECT id, user, product, amount FROM cart_items WHERE user = ?", - -1, - &stmt, - NULL); - sqlite3_bind_int64(stmt, 1, user_id); - - while ((sqlite_res = sqlite3_step(stmt)) == SQLITE_ROW) { - CartItem cart_item = { - .id = GET_INT(0), - .user_id = GET_INT(1), - .product_id = GET_INT(2), - .amount = GET_INT(3), - }; - cart_item_vec_push(vec, cart_item); - } - if (sqlite_res != SQLITE_DONE) { - fprintf(stderr, "error: %s\n", sqlite3_errmsg(connection)); - res = DbRes_Error; - goto l0_return; - } - - res = DbRes_Ok; -l0_return: - if (stmt) - sqlite3_finalize(stmt); - DISCONNECT; - return res; -} diff --git a/backend/src/main.c b/backend/src/main.c index 7a7771a..cde38d9 100644 --- a/backend/src/main.c +++ b/backend/src/main.c @@ -24,11 +24,8 @@ int main(void) Db* db = db_sqlite_new(); - Cx cx = { - .number = 1, - .db = db, - }; - session_vec_construct(&cx.sessions); + Cx cx; + cx_construct(&cx, db); server = http_server_new((HttpServerOpts) { .port = 8080, @@ -59,6 +56,7 @@ int main(void) http_server_listen(server); http_server_free(server); + cx_destroy(&cx); db_sqlite_free(db); }