mirror of
https://github.com/logicog/RTLPlayground.git
synced 2026-10-29 17:54:14 +08:00
httpd: four login sessions instead of one
Logging in from a second browser ended the first one's session at its next request: two browsers open on the switch logged each other out every few seconds. Up to four sessions now, each with its own cookie and expiry; a fifth login replaces the least recently used. The expiry check is a leaf function so its 32-bit scratch stays out of internal RAM (stack still 159 bytes with HEALTH). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Tx2W7xVecMoKbBCkD2i8PG (cherry picked from commit 03330f4077ef8872d861d951c8e44ece3c573935)
This commit is contained in:
1 parent
a18c334139
commit
70f59b64f5
1 file changed
+50
-14
+50
-14
@@ -75,10 +75,15 @@ __xdata uint8_t postbody_endpoint;
|
||||
__xdata uint16_t postbody_start;
|
||||
|
||||
__xdata char passwd[21];
|
||||
__xdata char session_id[SESSION_ID_LENGTH + 1];
|
||||
/* Up to SESSIONS logins at once, each with its own cookie and its own
|
||||
* expiry. With a single one, logging in from a second browser (or a phone)
|
||||
* ended the first browser's session at its next request. */
|
||||
#define SESSIONS 4
|
||||
__xdata char session_id[SESSIONS][SESSION_ID_LENGTH + 1];
|
||||
__xdata uint32_t last_session_use[SESSIONS];
|
||||
__xdata uint8_t session_slot;
|
||||
__xdata uint8_t authenticated;
|
||||
__xdata uint32_t now;
|
||||
__xdata uint32_t last_session_use;
|
||||
|
||||
#define TSTATE_NONE 0
|
||||
#define TSTATE_TX 1
|
||||
@@ -109,6 +114,33 @@ void httpd_init(void) __banked
|
||||
// handling one, and nothing has set it yet at init time.
|
||||
for (uint8_t i = 0; i < UIP_CONNS; i++)
|
||||
uip_conns[i].appstate.tstate = TSTATE_CLOSED;
|
||||
for (session_slot = 0; session_slot < SESSIONS; session_slot++)
|
||||
session_id[session_slot][0] = NUL;
|
||||
}
|
||||
|
||||
/* Leaf functions, so the compiler keeps their 32-bit scratch in the overlay
|
||||
* rather than in internal RAM. */
|
||||
static uint8_t session_stale(void)
|
||||
{
|
||||
if (now - last_session_use[session_slot] > session_timeout)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* For a new login: a free or expired slot, else the least recently used. */
|
||||
static void session_pick(void)
|
||||
{
|
||||
__xdata uint8_t i;
|
||||
__xdata uint8_t oldest = 0;
|
||||
|
||||
for (i = 0; i < SESSIONS; i++) {
|
||||
session_slot = i;
|
||||
if (!session_id[i][0] || session_stale())
|
||||
return;
|
||||
if (last_session_use[i] < last_session_use[oldest])
|
||||
oldest = i;
|
||||
}
|
||||
session_slot = oldest;
|
||||
}
|
||||
|
||||
|
||||
@@ -343,15 +375,17 @@ __xdata uint8_t *scan_header(__xdata uint8_t * __xdata p)
|
||||
|
||||
read_reg_timer(&now);
|
||||
|
||||
if (session && session_id[0]) {
|
||||
if (now - last_session_use > session_timeout) {
|
||||
dbg_string("Session expired\n");
|
||||
} else {
|
||||
if (is_word_x(session, session_id)) {
|
||||
if (session) {
|
||||
for (session_slot = 0; session_slot < SESSIONS; session_slot++) {
|
||||
if (!session_id[session_slot][0])
|
||||
continue;
|
||||
if (session_stale()) {
|
||||
dbg_string("Session expired\n");
|
||||
session_id[session_slot][0] = NUL;
|
||||
} else if (is_word_x(session, session_id[session_slot])) {
|
||||
authenticated = 1;
|
||||
last_session_use = now;
|
||||
} else {
|
||||
dbg_string("Invalid session cookie!\n");
|
||||
last_session_use[session_slot] = now;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -675,13 +709,15 @@ static void run_login_body(__xdata uint8_t *body)
|
||||
{
|
||||
if (strstart(body, "pwd=") && is_url_word_x(body + 4, passwd)) {
|
||||
dbg_string("Password accepted!\n");
|
||||
read_reg_timer(&last_session_use);
|
||||
gen_random_hex_chars(session_id, SESSION_ID_LENGTH);
|
||||
session_id[SESSION_ID_LENGTH] = NUL;
|
||||
read_reg_timer(&now);
|
||||
session_pick();
|
||||
last_session_use[session_slot] = now;
|
||||
gen_random_hex_chars(session_id[session_slot], SESSION_ID_LENGTH);
|
||||
session_id[session_slot][SESSION_ID_LENGTH] = NUL;
|
||||
slen = strtox(outbuf, "HTTP/1.1 302 Found\r\nConnection: close\r\nLocation: index.html\r\n" \
|
||||
"Set-Cookie: session=");
|
||||
for (uint8_t i = 0; i < SESSION_ID_LENGTH; i++)
|
||||
outbuf[slen++] = session_id[i];
|
||||
outbuf[slen++] = session_id[session_slot][i];
|
||||
slen += strtox(outbuf + slen, "; SameSite=Strict\r\n\r\n");
|
||||
} else {
|
||||
dbg_string("Password invalid!\n");
|
||||
|
||||
Reference in new issue
Block a user