Files
mongoose/src/net.h
T
2026-06-11 19:56:57 +01:00

188 lines
10 KiB
C

#pragma once
#include "arch.h"
#include "config.h"
#include "event.h"
#include "iobuf.h"
#include "net_builtin.h"
#include "str.h"
#include "timer.h"
// DNS server configuration used by struct mg_mgr.
struct mg_dns {
const char *url; // DNS server URL, e.g. "udp://8.8.8.8:53"
struct mg_connection *c; // Active DNS connection; NULL when idle
};
// Network address: IPv4 or IPv6 address plus port. All values in network byte order.
struct mg_addr {
union { // IP address bytes in network byte order
uint8_t ip[16]; // Raw 16-byte buffer; IPv4 uses the first 4 bytes
uint32_t ip4; // IPv4 address alias (same storage as ip[0..3])
uint64_t ip6[2]; // IPv6 address as two 64-bit words
} addr;
uint16_t port; // TCP or UDP port in network byte order
uint8_t scope_id; // IPv6 scope ID (from the %N suffix in the address)
bool is_ip6; // True when this address holds an IPv6 address
};
// Central event manager. Zero-initialise with mg_mgr_init() before use.
struct mg_mgr {
struct mg_connection *conns; // Linked list of all open connections
struct mg_dns dns4; // IPv4 DNS server (default: 8.8.8.8:53)
struct mg_dns dns6; // IPv6 DNS server (default: [2001:4860:4860::8888]:53)
struct mg_connection *mdns; // mDNS listener connection, or NULL
int dnstimeout; // DNS resolve timeout in ms (default: 3000)
bool use_dns6; // If true, prefer DNS6 for hostname resolution
unsigned long nextid; // Auto-incrementing counter for connection IDs
void *userdata; // Arbitrary user pointer (initially set to mg_fw_version)
void *tls_ctx; // Shared TLS context for all TLS connections
uint16_t mqtt_id; // Packet ID counter for MQTT pub/sub
void *active_dns_requests; // Pending DNS queries (internal)
void *active_mdns_requests; // Pending mDNS resolver queries (internal)
struct mg_timer *timers; // Linked list of active timers
int epoll_fd; // epoll file descriptor; -1 when unused (MG_EPOLL_ENABLE=1)
struct mg_tcpip_if *ifp; // Builtin TCP/IP stack: network interface pointer
size_t extraconnsize; // Builtin TCP/IP stack: extra bytes allocated per connection
MG_SOCKET_TYPE pipe; // Socketpair write-end used by mg_wakeup()
#if MG_ENABLE_FREERTOS_TCP
SocketSet_t ss; // FreeRTOS-TCP socket set
#endif
};
// A single network connection. Do not allocate directly; use mg_connect() or
// mg_listen(). Each connection has an event handler fn called for every event.
struct mg_connection {
struct mg_connection *next; // Next connection in mgr->conns linked list
struct mg_mgr *mgr; // Manager that owns this connection
struct mg_addr loc; // Local address (IP + port)
struct mg_addr rem; // Remote address (IP + port)
void *fd; // OS socket handle or LWIP PCB pointer
unsigned long id; // Unique, auto-incrementing connection ID
struct mg_iobuf recv; // Received data; consume in MG_EV_READ handler
struct mg_iobuf send; // Data to send; append with mg_send() / mg_printf()
struct mg_iobuf prof; // Profiling data (MG_ENABLE_PROFILE only)
struct mg_iobuf rtls; // TLS only: encrypted data buffered before decryption
mg_event_handler_t fn; // User event handler
void *fn_data; // User-supplied argument passed to fn
mg_event_handler_t pfn; // Protocol-level handler (set by protocol modules)
void *pfn_data; // Protocol-level handler argument
char data[MG_DATA_SIZE]; // Scratch space for protocol state; freely readable
void *tls; // TLS state (internal)
unsigned is_listening : 1; // Listening connection; accepts inbound connections
unsigned is_client : 1; // Outbound connection created by mg_connect()
unsigned is_accepted : 1; // Inbound connection accepted from a listener
unsigned is_resolving : 1; // DNS resolution is in progress
unsigned is_arplooking : 1; // ARP resolution is in progress (builtin TCP/IP)
unsigned is_connecting : 1; // Non-blocking TCP connect is in progress
unsigned is_tls : 1; // TLS connection
unsigned is_tls_hs : 1; // TLS handshake is in progress
unsigned is_udp : 1; // UDP connection (not TCP)
unsigned is_websocket : 1; // WebSocket connection
unsigned is_mqtt5 : 1; // MQTT5 connection (set by mg_mqtt_login)
unsigned is_hexdumping : 1; // Log hex dump of all in/out traffic
unsigned is_draining : 1; // Flush send buffer, then close
unsigned is_closing : 1; // Close and free immediately on next poll
unsigned is_full : 1; // Pause incoming reads until cleared
unsigned is_tls_throttled : 1; // TLS write was throttled; retry pending
unsigned is_resp : 1; // HTTP: response is still being generated
unsigned is_readable : 1; // Socket is ready to read (epoll/select)
unsigned is_writable : 1; // Socket is ready to write (epoll/select)
};
// Runs one iteration of the event loop. Waits up to ms milliseconds for I/O
// events (0 = return immediately). Calls event handlers for all ready
// connections and fires expired timers. Call in a tight loop:
// while (keep_running) mg_mgr_poll(&mgr, 50);
void mg_mgr_poll(struct mg_mgr *, int ms);
// Initialises mgr to a safe zero state and sets defaults: DNS servers,
// 3-second DNS timeout, epoll/SIGPIPE setup, TLS context. Must be called
// before any other mg_* function. Overwrite mgr->userdata afterwards if needed.
void mg_mgr_init(struct mg_mgr *);
// Closes all connections, frees all timers, and releases the TLS context.
// Safe to call on a partially initialised mgr.
void mg_mgr_free(struct mg_mgr *);
// Creates a listening connection on url (e.g. "tcp://0.0.0.0:8080").
// Fires MG_EV_OPEN on the listener, then MG_EV_ACCEPT for each new client.
// Returns NULL on error.
struct mg_connection *mg_listen(struct mg_mgr *, const char *url,
mg_event_handler_t fn, void *fn_data);
// Opens an outbound connection to url (e.g. "tcp://example.com:80").
// DNS resolution is asynchronous. Fires MG_EV_RESOLVE, then MG_EV_CONNECT
// when the connection is established (or MG_EV_ERROR on failure).
// Returns NULL on error (OOM, network down, null url).
struct mg_connection *mg_connect(struct mg_mgr *, const char *url,
mg_event_handler_t fn, void *fn_data);
// Wraps an existing OS file descriptor in a Mongoose connection.
// The connection is added to mgr and fires MG_EV_OPEN immediately.
// Useful for integrating pre-opened sockets (e.g. stdin, accept() fd).
struct mg_connection *mg_wrapfd(struct mg_mgr *mgr, int fd,
mg_event_handler_t fn, void *fn_data);
// Called internally after DNS resolution completes to create the OS socket
// and initiate the TCP/IP connect. Normally not called by user code.
void mg_connect_resolved(struct mg_connection *);
// Appends buf/len to c->send. Returns true on success, false on OOM
// (which also fires MG_EV_ERROR and schedules the connection for close).
// Data is sent asynchronously by the next mg_mgr_poll() call.
bool mg_send(struct mg_connection *, const void *, size_t);
// Formats and appends to c->send using printf-style format string.
// Returns bytes written, or 0 on OOM. Supports all mg_xprintf specifiers
// including %M/%m custom printers. See fmt.h for the full specifier list.
size_t mg_printf(struct mg_connection *, const char *fmt, ...);
size_t mg_vprintf(struct mg_connection *, const char *fmt, va_list *ap);
// Parses an IP address string str into addr. Handles "localhost", plain IPv4
// (e.g. "1.2.3.4"), IPv6 with optional brackets and scope ID, and
// IPv4-mapped IPv6 (::ffff:1.2.3.4). Does NOT parse the port.
// Returns true on success; addr->is_ip6 and addr->addr are set.
bool mg_aton(struct mg_str str, struct mg_addr *addr);
// Low-level functions for integrating with custom network stacks.
// Allocates a new connection struct with mgr->extraconnsize extra bytes.
// Returns NULL on OOM.
struct mg_connection *mg_alloc_conn(struct mg_mgr *);
// Fires MG_EV_CLOSE, frees all buffers (recv/send/rtls), removes c from
// mgr->conns, and calls mg_free(c). Do not use c after this call.
void mg_close_conn(struct mg_connection *c);
// Creates and binds the OS socket for a listening connection c at url.
// Called internally by mg_listen(); expose for custom network stack use.
// Returns false on error.
bool mg_open_listener(struct mg_connection *c, const char *url);
// Thread-safe wakeup: fires MG_EV_WAKEUP on the connection whose id matches,
// with ev_data pointing to an mg_str containing buf/len.
// Requires mg_wakeup_init() to have been called first.
// Returns false if the pipe is not initialised or conn_id is 0.
// Safe to call from any thread or interrupt context.
bool mg_wakeup(struct mg_mgr *, unsigned long id, const void *buf, size_t len);
// Initialises the internal socketpair used by mg_wakeup(). Call once after
// mg_mgr_init() if you intend to wake the event loop from another thread.
// Returns false on failure (e.g. socketpair creation failed).
bool mg_wakeup_init(struct mg_mgr *);
// Deprecated API, do not expose. Use mg_timer_expired instead
struct mg_timer *mg_timer_add(struct mg_mgr *mgr, uint64_t milliseconds,
unsigned flags, void (*fn)(void *), void *arg);
// Like mg_connect() but also sets a protocol-level handler pfn/pfn_data.
// Used internally by protocol modules (MQTT, WebSocket, etc.).
struct mg_connection *mg_connect_svc(struct mg_mgr *mgr, const char *url,
mg_event_handler_t fn, void *fn_data,
mg_event_handler_t pfn, void *pfn_data);
// Restores c->rem from a saved address buffer written by the caller, then
// maps the IP back through the builtin TCP/IP stack. Used after a UDP
// multicast send to restore the connection's original remote address.
void mg_multicast_restore(struct mg_connection *c, uint8_t *from);