Add 30-second idle and 60-second pre-request deadlines, updates activity timestamps during TCP/TLS progress, and apply receive timeouts to emulation sockets.

This prevents incomplete plaintext or TLS requests from occupying a connection indefinitely, including byte-trickle attempts.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
This commit is contained in:
Pol Henarejos
2026-07-12 20:42:56 +02:00
parent 799e78d2e1
commit 154682db4a
3 changed files with 39 additions and 3 deletions
+29 -1
View File
@@ -52,6 +52,7 @@ typedef int socket_t;
#include <netinet/in.h>
#include <pthread.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <unistd.h>
#endif
#else
@@ -61,6 +62,8 @@ typedef int socket_t;
#define REST_SESSION_TIMEOUT_INACTIVITY_MS (10 * 60 * 1000) // 10 minutes
#define REST_SESSION_TIMEOUT_TOTAL_MS (2 * 60 * 60 * 1000) // 2 hours
#define REST_CONN_TIMEOUT_MS (30 * 1000)
#define REST_CONN_TOTAL_TIMEOUT_MS (60 * 1000)
#ifndef ENABLE_EMULATION
static struct tcp_pcb *listener_pcb = NULL;
@@ -287,6 +290,8 @@ static rest_conn_t *alloc_conn(
if (!conns[i].in_use) {
memset(&conns[i], 0, sizeof(conns[i]));
conns[i].in_use = true;
conns[i].opened_ms = board_millis();
conns[i].last_progress_ms = board_millis();
#ifdef ENABLE_EMULATION
conns[i].sock = sock;
struct sockaddr_in addr;
@@ -1214,6 +1219,7 @@ static err_t rest_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err
}
pbuf_copy_partial(p, buffer + *len, p->tot_len, 0);
*len += p->tot_len;
conn->last_progress_ms = board_millis();
tcp_recved(pcb, p->tot_len);
pbuf_free(p);
if (conn->conn_type == REST_CONN_TLS) {
@@ -1226,6 +1232,15 @@ static err_t rest_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err
static err_t rest_poll(void *arg, struct tcp_pcb *pcb) {
rest_conn_t *conn = (rest_conn_t *)arg;
LWIP_UNUSED_ARG(pcb);
if (conn == NULL) {
return ERR_OK;
}
uint32_t now = board_millis();
if (now - conn->last_progress_ms >= REST_CONN_TIMEOUT_MS ||
(!conn->request_dispatched && now - conn->opened_ms >= REST_CONN_TOTAL_TIMEOUT_MS)) {
rest_close_conn(conn);
return ERR_ABRT;
}
if (conn != NULL && conn->tx_pending) {
return rest_lwip_continue_send(conn);
}
@@ -1379,15 +1394,27 @@ static void *rest_emulation_thread(void *arg) {
(void)close(accepted);
continue;
}
#ifndef _MSC_VER
{
struct timeval timeout = { .tv_sec = REST_CONN_TIMEOUT_MS / 1000, .tv_usec = 0 };
(void)setsockopt(accepted, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
}
#endif
if (conn->conn_type == REST_CONN_TLS) {
mbedtls_ssl_init(&conn->ssl);
if (mbedtls_ssl_setup(&conn->ssl, &tls_conf) != 0) {
rest_close_conn(conn);
continue;
}
mbedtls_ssl_set_bio(&conn->ssl, &conn->sock, tls_send_cb, tls_recv_cb, NULL);
mbedtls_ssl_set_bio(&conn->ssl, conn, tls_send_cb, tls_recv_cb, NULL);
}
while (conn->in_use) {
uint32_t now = board_millis();
if (now - conn->last_progress_ms >= REST_CONN_TIMEOUT_MS ||
(!conn->request_dispatched && now - conn->opened_ms >= REST_CONN_TOTAL_TIMEOUT_MS)) {
rest_close_conn(conn);
break;
}
if (conn->conn_type == REST_CONN_TLS) {
/* TLS on emulation reads directly from socket through mbedtls BIO callbacks. */
if (tls_progress_conn(conn) != ERR_OK) {
@@ -1402,6 +1429,7 @@ static void *rest_emulation_thread(void *arg) {
break;
}
conn->request_len += (size_t)n;
conn->last_progress_ms = board_millis();
if (conn->request_len > REST_MAX_REQUEST_SIZE) {
send_json_error(conn, 413, "payload_too_large");
break;
+2
View File
@@ -57,6 +57,8 @@ typedef struct {
struct tcp_pcb *pcb;
#endif
size_t request_len;
uint32_t opened_ms;
uint32_t last_progress_ms;
rest_conn_type_t conn_type;
#ifdef _MSC_VER
char _padding[sizeof(void *) - sizeof(rest_conn_type_t)];
+8 -2
View File
@@ -191,9 +191,11 @@ int emulation_rest_tls_port(void) {
}
int tls_send_cb(void *ctx, const unsigned char *buf, size_t len) {
const socket_t fd = (socket_t)(*(const intptr_t *)ctx);
rest_conn_t *conn = (rest_conn_t *)ctx;
const socket_t fd = conn->sock;
ssize_t r = send(fd, (const char *)buf, (int)len, 0);
if (r >= 0) {
conn->last_progress_ms = board_millis();
return (int)r;
}
#ifdef _MSC_VER
@@ -212,9 +214,11 @@ int tls_send_cb(void *ctx, const unsigned char *buf, size_t len) {
}
int tls_recv_cb(void *ctx, unsigned char *buf, size_t len) {
const socket_t fd = (socket_t)(*(const intptr_t *)ctx);
rest_conn_t *conn = (rest_conn_t *)ctx;
const socket_t fd = conn->sock;
ssize_t r = recv(fd, (char *)buf, (int)len, 0);
if (r > 0) {
conn->last_progress_ms = board_millis();
return (int)r;
}
if (r == 0) {
@@ -313,6 +317,7 @@ err_t tls_progress_conn(rest_conn_t *conn) {
return ERR_ABRT;
}
conn->handshake_done = true;
conn->last_progress_ms = board_millis();
}
while (!conn->request_complete) {
@@ -326,6 +331,7 @@ err_t tls_progress_conn(rest_conn_t *conn) {
return ERR_ABRT;
}
conn->request_len += (size_t)ret;
conn->last_progress_ms = board_millis();
conn->request[conn->request_len] = '\0';
ret = request_is_complete(conn->request, conn->request_len, &payload_offset, &payload_len);
if (ret < 0) {