upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/main/session.c
diff options
context:
space:
mode:
Diffstat (limited to 'main/session.c')
-rw-r--r--main/session.c164
1 files changed, 164 insertions, 0 deletions
diff --git a/main/session.c b/main/session.c
new file mode 100644
index 0000000..6d9c334
--- /dev/null
+++ b/main/session.c
@@ -0,0 +1,164 @@
1#include "session.h"
2#include "firewall.h"
3#include "dns_server.h"
4#include "esp_log.h"
5#include "freertos/FreeRTOS.h"
6#include "freertos/task.h"
7#include <string.h>
8
9#define SPENT_SECRETS_MAX 100
10
11static const char *TAG = "session";
12static session_t s_sessions[SESSION_MAX_CLIENTS];
13static int s_session_count = 0;
14
15static char s_spent_secrets[SPENT_SECRETS_MAX][65];
16static int s_spent_count = 0;
17
18static int64_t get_time_ms(void)
19{
20 return (int64_t)xTaskGetTickCount() * portTICK_PERIOD_MS;
21}
22
23esp_err_t session_manager_init(void)
24{
25 memset(s_sessions, 0, sizeof(s_sessions));
26 s_session_count = 0;
27 s_spent_count = 0;
28 ESP_LOGI(TAG, "Session manager initialized");
29 return ESP_OK;
30}
31
32session_t *session_create(uint32_t client_ip, uint64_t allotment_ms,
33 const char *spent_secrets[], int secret_count)
34{
35 session_t *existing = session_find_by_ip(client_ip);
36 if (existing) {
37 session_extend(existing, allotment_ms);
38 for (int i = 0; i < secret_count && s_spent_count < SPENT_SECRETS_MAX; i++) {
39 strncpy(s_spent_secrets[s_spent_count], spent_secrets[i], 64);
40 s_spent_secrets[s_spent_count][64] = '\0';
41 s_spent_count++;
42 }
43 return existing;
44 }
45
46 if (s_session_count >= SESSION_MAX_CLIENTS) {
47 for (int i = 0; i < SESSION_MAX_CLIENTS; i++) {
48 if (!s_sessions[i].active || session_is_expired(&s_sessions[i])) {
49 session_revoke(&s_sessions[i]);
50 break;
51 }
52 }
53 }
54
55 for (int i = 0; i < SESSION_MAX_CLIENTS; i++) {
56 if (!s_sessions[i].active) {
57 s_sessions[i].client_ip = client_ip;
58 s_sessions[i].allotment_ms = allotment_ms;
59 s_sessions[i].start_time_ms = get_time_ms();
60 s_sessions[i].active = true;
61 s_sessions[i].spent_secret_count = 0;
62
63 for (int j = 0; j < secret_count && j < 5; j++) {
64 strncpy(s_sessions[i].spent_secrets[s_sessions[i].spent_secret_count],
65 spent_secrets[j], 64);
66 s_sessions[i].spent_secrets[s_sessions[i].spent_secret_count][64] = '\0';
67 s_sessions[i].spent_secret_count++;
68 }
69
70 for (int j = 0; j < secret_count && s_spent_count < SPENT_SECRETS_MAX; j++) {
71 strncpy(s_spent_secrets[s_spent_count], spent_secrets[j], 64);
72 s_spent_secrets[s_spent_count][64] = '\0';
73 s_spent_count++;
74 }
75
76 s_session_count++;
77 firewall_grant_access(client_ip);
78
79 esp_ip4_addr_t ip = { .addr = client_ip };
80 ESP_LOGI(TAG, "Session created: " IPSTR " allotment=%llums", IP2STR(&ip),
81 (unsigned long long)allotment_ms);
82 return &s_sessions[i];
83 }
84 }
85
86 ESP_LOGW(TAG, "No free session slots");
87 return NULL;
88}
89
90session_t *session_find_by_ip(uint32_t client_ip)
91{
92 for (int i = 0; i < SESSION_MAX_CLIENTS; i++) {
93 if (s_sessions[i].active && s_sessions[i].client_ip == client_ip) {
94 return &s_sessions[i];
95 }
96 }
97 return NULL;
98}
99
100void session_extend(session_t *session, uint64_t additional_ms)
101{
102 if (!session || !session->active) return;
103 session->allotment_ms += additional_ms;
104 esp_ip4_addr_t ip = { .addr = session->client_ip };
105 ESP_LOGI(TAG, "Session extended: " IPSTR " +%llums (total=%llu)", IP2STR(&ip),
106 (unsigned long long)additional_ms, (unsigned long long)session->allotment_ms);
107}
108
109bool session_is_expired(const session_t *session)
110{
111 if (!session || !session->active) return true;
112 int64_t elapsed = get_time_ms() - session->start_time_ms;
113 return elapsed >= (int64_t)session->allotment_ms;
114}
115
116bool session_is_secret_spent(const char *secret)
117{
118 for (int i = 0; i < s_spent_count; i++) {
119 if (strncmp(s_spent_secrets[i], secret, 64) == 0) return true;
120 }
121 return false;
122}
123
124void session_check_expiry(void)
125{
126 for (int i = 0; i < SESSION_MAX_CLIENTS; i++) {
127 if (s_sessions[i].active && session_is_expired(&s_sessions[i])) {
128 esp_ip4_addr_t ip = { .addr = s_sessions[i].client_ip };
129 ESP_LOGI(TAG, "Session expired: " IPSTR, IP2STR(&ip));
130 session_revoke(&s_sessions[i]);
131 }
132 }
133}
134
135void session_revoke(session_t *session)
136{
137 if (!session || !session->active) return;
138 firewall_revoke_access(session->client_ip);
139 session->active = false;
140 s_session_count--;
141}
142
143void session_revoke_all(void)
144{
145 for (int i = 0; i < SESSION_MAX_CLIENTS; i++) {
146 if (s_sessions[i].active) {
147 session_revoke(&s_sessions[i]);
148 }
149 }
150}
151
152int session_active_count(void)
153{
154 int count = 0;
155 for (int i = 0; i < SESSION_MAX_CLIENTS; i++) {
156 if (s_sessions[i].active) count++;
157 }
158 return count;
159}
160
161void session_tick(void)
162{
163 session_check_expiry();
164}