Files
Vermix-Gate/lib/data/session.cpp
T
2025-10-06 18:27:50 +02:00

108 lines
3.7 KiB
C++

#include "session.hpp"
#include <pgmspace.h> // Required for PROGMEM
// Definition of the global instance
SessionManager sessionManager;
// The character set is now stored in flash memory to save RAM.
const char charset[] PROGMEM = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
SessionManager::SessionManager() {
session_mutex_ = xSemaphoreCreateMutex();
for (size_t i = 0; i < MAX_SESSIONS; ++i) {
sessions_[i].username[0] = '\0';
}
}
SessionManager::~SessionManager() {
vSemaphoreDelete(session_mutex_);
}
const char* SessionManager::createSession(const char* username) {
const char* result_token = nullptr;
// Lock the mutex to ensure exclusive access to the sessions array.
if (xSemaphoreTake(session_mutex_, portMAX_DELAY) == pdTRUE) {
for (size_t i = 0; i < MAX_SESSIONS; ++i) {
if (sessions_[i].username[0] == '\0') {
strncpy(sessions_[i].username, username, sizeof(sessions_[i].username) - 1);
sessions_[i].username[sizeof(sessions_[i].username) - 1] = '\0';
generateToken(sessions_[i].token, sizeof(sessions_[i].token));
sessions_[i].expiry_time = millis() + (15 * 60 * 1000);
result_token = sessions_[i].token;
break; // Exit loop once a slot is found
}
}
xSemaphoreGive(session_mutex_); // Release the mutex
}
return result_token;
}
const char* SessionManager::validateSession(const char* token) {
if (token == nullptr) {
return nullptr;
}
// We must copy the username to a static buffer, because the session array
// could be modified by another task after we release the mutex.
static char valid_username[33];
valid_username[0] = '\0';
if (xSemaphoreTake(session_mutex_, portMAX_DELAY) == pdTRUE) {
for (size_t i = 0; i < MAX_SESSIONS; ++i) {
if (sessions_[i].username[0] != '\0' && strcmp(sessions_[i].token, token) == 0) {
if (millis() < sessions_[i].expiry_time) {
strcpy(valid_username, sessions_[i].username);
} else {
sessions_[i].username[0] = '\0'; // Expired, clear it
}
break;
}
}
xSemaphoreGive(session_mutex_);
}
return (valid_username[0] != '\0') ? valid_username : nullptr;
}
bool SessionManager::endSession(const char* token) {
if (token == nullptr) return false;
bool found = false;
if (xSemaphoreTake(session_mutex_, portMAX_DELAY) == pdTRUE) {
for (size_t i = 0; i < MAX_SESSIONS; ++i) {
if (sessions_[i].username[0] != '\0' && strcmp(sessions_[i].token, token) == 0) {
sessions_[i].username[0] = '\0';
found = true;
break;
}
}
xSemaphoreGive(session_mutex_);
}
return found;
}
void SessionManager::cleanupExpiredSessions() {
unsigned long current_time = millis();
if (xSemaphoreTake(session_mutex_, portMAX_DELAY) == pdTRUE) {
for (size_t i = 0; i < MAX_SESSIONS; ++i) {
if (sessions_[i].username[0] != '\0') {
if (current_time >= sessions_[i].expiry_time) {
sessions_[i].username[0] = '\0';
}
}
}
xSemaphoreGive(session_mutex_);
}
}
void SessionManager::generateToken(char* buffer, size_t buffer_size) {
const size_t charset_size = sizeof(charset) - 1;
for (size_t i = 0; i < buffer_size - 1; ++i) {
// Read the character directly from flash memory (PROGMEM).
buffer[i] = pgm_read_byte(&charset[esp_random() % charset_size]);
}
buffer[buffer_size - 1] = '\0';
}