21#include "freertos/FreeRTOS.h"
22#include "freertos/queue.h"
26static struct tcp_pcb *listen_pcb =
nullptr;
28static StaticQueue_t _queue_struct;
34static err_t lowlevel_accept_cb(
void *arg,
struct tcp_pcb *newpcb, err_t err);
35static err_t lowlevel_recv_cb(
void *arg,
struct tcp_pcb *tpcb,
struct pbuf *p, err_t err);
36static err_t lowlevel_sent_cb(
void *arg,
struct tcp_pcb *tpcb, u16_t len);
37static void lowlevel_err_cb(
void *arg, err_t err);
47static inline void enqueue(
const TcpEvt &evt)
68 _queue_storage, &_queue_struct);
79 struct tcp_pcb *pcb = tcp_new_ip_type(IPADDR_TYPE_ANY);
83 err_t err = tcp_bind(pcb, IP_ANY_TYPE, port);
90 listen_pcb = tcp_listen_with_backlog(pcb,
MAX_CONNS);
97 tcp_arg(listen_pcb,
nullptr);
98 tcp_accept(listen_pcb, lowlevel_accept_cb);
108 tcp_close(listen_pcb);
109 listen_pcb =
nullptr;
120 tcp_arg(pcb,
nullptr);
137 uint32_t now = millis();
146 struct tcp_pcb *pcb = slot->
pcb;
156 tcp_arg(pcb,
nullptr);
175static err_t lowlevel_accept_cb(
void *arg,
struct tcp_pcb *newpcb, err_t err)
177 if (err != ERR_OK || newpcb ==
nullptr)
207 tcp_arg(newpcb, slot);
208 tcp_recv(newpcb, lowlevel_recv_cb);
209 tcp_sent(newpcb, lowlevel_sent_cb);
210 tcp_err(newpcb, lowlevel_err_cb);
225static err_t lowlevel_recv_cb(
void *arg,
struct tcp_pcb *tpcb,
struct pbuf *p, err_t err)
240 tcp_arg(tpcb,
nullptr);
241 if (tcp_close(tpcb) != ERR_OK)
250 size_t bytes_copied = 0;
253 while (q !=
nullptr && !full)
255 uint8_t *payload = (uint8_t *)q->payload;
256 for (u16_t i = 0; i < q->len; i++)
259 if (next_head == slot->
rx_tail)
276 tcp_recved(tpcb, (u16_t)bytes_copied);
279 if (bytes_copied > 0)
294static err_t lowlevel_sent_cb(
void *arg,
struct tcp_pcb *tpcb, u16_t len)
309static void lowlevel_err_cb(
void *arg, err_t err)
#define CONN_TIMEOUT_MS
Compile-time default for connection idle timeout in milliseconds.
#define RX_BUF_SIZE
Ring-buffer capacity in bytes per connection slot.
#define EVT_QUEUE_DEPTH
Depth of the FreeRTOS event queue shared between lwIP callbacks and the main-loop task.
#define MAX_CONNS
Maximum simultaneous TCP connections.
static bool heap_available()
Always returns true — no heap allocation means no pre-flight needed.
static void check_timeouts()
Scan the pool and force-close connections idle for > conn_timeout_ms.
static int32_t init(uint16_t port, const WebServerConfig *cfg=nullptr)
Initialise the TCP stack, create the event queue, and begin listening.
static size_t heap_needed()
Always returns 0 — the library makes no heap allocations.
static uint32_t conn_timeout_ms
Runtime connection-idle timeout in milliseconds.
static void stop()
Stop the server: abort all connections, close the listener, free the queue.
static QueueHandle_t queue
FreeRTOS queue handle shared between lwIP callbacks and server_tick().
A single TCP connection context.
volatile ConnState state
Lifecycle state; volatile for inter-task visibility.
struct tcp_pcb * pcb
lwIP PCB; null when slot is free.
volatile size_t rx_tail
Consumer read index (main-loop context).
uint32_t last_activity_ms
millis() timestamp of last TX/RX event.
uint8_t id
Fixed slot index (0 … MAX_CONNS-1).
uint8_t rx_buffer[RX_BUF_SIZE]
Ring buffer storage.
volatile size_t rx_head
Producer write index (lwIP context).
Event record posted from lwIP callbacks to the main-loop task.
Runtime-tunable server parameters.
TcpConn conn_pool[MAX_CONNS]
Static pool of connection contexts. Defined in transport.cpp.
Layer 4 (Transport) — TCP connection pool, ring buffers, and lwIP integration.
@ CONN_FREE
Slot is available; no PCB is attached.
@ CONN_ACTIVE
Live connection; PCB is valid.
@ EVT_CONNECT
New connection accepted.
@ EVT_DISCONNECT
Remote peer closed the connection gracefully.
@ EVT_ERROR
lwIP reported an error (PCB may already be freed).
@ EVT_DATA
Data received; bytes are already in the ring buffer.
TcpConn conn_pool[MAX_CONNS]
Static pool of connection contexts. Defined in transport.cpp.