From fa07b59cc7e3c8dca7bd366ce0aa7085531faf22 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Mon, 20 Apr 2026 13:01:23 +0200 Subject: [PATCH] Add REST session handling. Signed-off-by: Pol Henarejos --- src/usb/lwip/rest.c | 84 +++++++++++++++++++++++++++++++++++++++++++++ src/usb/lwip/rest.h | 42 +++++++++++++++++++++++ 2 files changed, 126 insertions(+) diff --git a/src/usb/lwip/rest.c b/src/usb/lwip/rest.c index fd408e9..5108402 100644 --- a/src/usb/lwip/rest.c +++ b/src/usb/lwip/rest.c @@ -17,6 +17,90 @@ #include "rest.h" #include +#include "random.h" + +#define REST_MAX_SESSIONS 4 + +static rest_session_t rest_sessions[REST_MAX_SESSIONS] = {0}; + +rest_session_t *rest_session_create(const rest_session_role_t role, rest_session_status_t status) { + for (int i = 0; i < REST_MAX_SESSIONS; i++) { + if (rest_sessions[i].status == REST_SESSION_UNKNOWN || rest_sessions[i].status == REST_SESSION_EXPIRED || rest_sessions[i].status == REST_SESSION_TERMINATED) { + memset(&rest_sessions[i], 0, sizeof(rest_session_t)); + rest_sessions[i].status = status; + rest_sessions[i].role = role; + random_fill_buffer(rest_sessions[i].id, sizeof(rest_sessions[i].id)); + rest_sessions[i].created_at = get_rtc_time(); + rest_sessions[i].last_activity_timestamp = rest_sessions[i].created_at; + return &rest_sessions[i]; + } + } + return NULL; +} + +rest_session_t *rest_session_get(const uint8_t *id, size_t id_len) { + if (id == NULL || id_len != 16) { + return NULL; + } + for (int i = 0; i < REST_MAX_SESSIONS; i++) { + if (rest_sessions[i].status != REST_SESSION_UNKNOWN && rest_sessions[i].status != REST_SESSION_EXPIRED && rest_sessions[i].status != REST_SESSION_TERMINATED) { + if (memcmp(rest_sessions[i].id, id, sizeof(rest_sessions[i].id)) == 0) { + return &rest_sessions[i]; + } + } + } + return NULL; +} + +int rest_session_terminate(const uint8_t *id, size_t id_len) { + rest_session_t *session = rest_session_get(id, id_len); + if (session == NULL) { + return -1; + } + session->status = REST_SESSION_TERMINATED; + return 0; +} + +int rest_session_update_activity(const uint8_t *id, size_t id_len) { + rest_session_t *session = rest_session_get(id, id_len); + if (session == NULL) { + return -1; + } + session->last_activity_timestamp = get_rtc_time(); + return 0; +} + +int rest_session_set_status(const uint8_t *id, size_t id_len, rest_session_status_t status) { + rest_session_t *session = rest_session_get(id, id_len); + if (session == NULL) { + return -1; + } + session->status = status; + return 0; +} + +int rest_session_set_role(const uint8_t *id, size_t id_len, rest_session_role_t role) { + rest_session_t *session = rest_session_get(id, id_len); + if (session == NULL) { + return -1; + } + session->role = role; + return 0; +} + +int rest_session_cleanup_expired(time_t expiration_time) { + int count = 0; + time_t now = get_rtc_time(); + for (int i = 0; i < REST_MAX_SESSIONS; i++) { + if (rest_sessions[i].status != REST_SESSION_UNKNOWN && rest_sessions[i].status != REST_SESSION_EXPIRED && rest_sessions[i].status != REST_SESSION_TERMINATED) { + if (now - rest_sessions[i].last_activity_timestamp > expiration_time) { + rest_sessions[i].status = REST_SESSION_EXPIRED; + count++; + } + } + } + return count; +} #ifdef DEBUG_APDU void rest_debug_dump_payload(const char *tag, const char *buffer, size_t len) { diff --git a/src/usb/lwip/rest.h b/src/usb/lwip/rest.h index 44f9395..b890137 100644 --- a/src/usb/lwip/rest.h +++ b/src/usb/lwip/rest.h @@ -22,7 +22,10 @@ #include #include #include +#include +#include #include "cJSON.h" +#include "pico_keys.h" #define REST_MAX_REQUEST_SIZE 1024 #define REST_MAX_METHOD_SIZE 8 @@ -54,12 +57,43 @@ typedef struct { typedef int (*rest_route_handler_t)(const rest_request_t *request, rest_response_t *response); +typedef enum { + REST_ROUTE_NONE = 0x0, + REST_ROUTE_AUTH = 0x1, +} rest_route_flags_t; + typedef struct { rest_http_method_t method; const char *path; rest_route_handler_t handler; + rest_route_flags_t flags; } rest_route_t; +typedef enum { + REST_SESSION_NONE = 0, + REST_SESSION_USER = 0x1, + REST_SESSION_ADMIN = 0x2 +} rest_session_role_t; + +typedef enum { + REST_SESSION_UNKNOWN = 0, + REST_SESSION_AUTH_PENDING = 0x1, + REST_SESSION_AUTHENTICATED = 0x2, + REST_SESSION_AUTH_FAILED = 0x3, + REST_SESSION_EXPIRED = 0x4, + REST_SESSION_INVALID = 0x5, + REST_SESSION_TERMINATED = 0x6, +} rest_session_status_t; + +typedef struct { + uint8_t id[16]; + time_t last_activity_timestamp; + time_t created_at; + uint32_t last_seq; + rest_session_role_t role; + rest_session_status_t status; +} rest_session_t; + extern int rest_execute_route_handler(const rest_request_t *request, rest_route_handler_t handler, rest_response_t *response); extern int rest_response_set_error(rest_response_t *response, int status_code, const char *message); @@ -69,6 +103,14 @@ bool rest_content_type_is_json(const char *content_type); const rest_route_t *rest_get_routes(size_t *count); +extern rest_session_t *rest_session_create(const rest_session_role_t role, rest_session_status_t status); +extern rest_session_t *rest_session_get(const uint8_t *id, size_t id_len); +extern int rest_session_terminate(const uint8_t *id, size_t id_len); +extern int rest_session_update_activity(const uint8_t *id, size_t id_len); +extern int rest_session_set_status(const uint8_t *id, size_t id_len, rest_session_status_t status); +extern int rest_session_set_role(const uint8_t *id, size_t id_len, rest_session_role_t role); +extern int rest_session_cleanup_expired(time_t expiration_time); + #ifdef DEBUG_APDU extern void rest_debug_dump_payload(const char *tag, const char *buffer, size_t len); #define REST_DEBUG_LOG(...) printf(__VA_ARGS__)