#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 }; union mg_pipe { MG_SOCKET_TYPE fd; void *q; }; // 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 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 union mg_pipe pipe; // Socketpair write-end / queue, 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. // // Example: // while (keep_running) mg_mgr_poll(&mgr, 50); // Full examples: // tutorials/http/http-server, tutorials/mqtt/mqtt-client, // tutorials/websocket/websocket-server, tutorials/core/timers // Related APIs: // mg_mgr_init(), mg_mgr_free(), mg_timer_add(), mg_wakeup() // Notes: // Waits up to ms milliseconds for I/O events; use ms=0 to return // immediately. Calls event handlers for ready connections and fires expired // timers. Call repeatedly from the main loop or a dedicated network task. void mg_mgr_poll(struct mg_mgr *, int ms); // Initialises an event manager before use. // // Example: // struct mg_mgr mgr; // mg_mgr_init(&mgr); // Full examples: // tutorials/http/http-server, tutorials/mqtt/mqtt-client, // tutorials/websocket/websocket-server, tutorials/core/embedded-filesystem // Related APIs: // mg_mgr_poll(), mg_mgr_free(), mg_http_listen(), mg_connect() // Notes: // Sets safe defaults such as DNS servers, DNS timeout, epoll/SIGPIPE setup, // and TLS context. Call before creating connections, listeners, or timers. // Set mgr.userdata after this call if your application needs it. // On embedded systems, if the built-in TCP/IP stack is enabled // (MG_ENABLE_TCPIP=1) and one built-in driver is selected, e.g. // MG_ENABLE_DRIVER_STM32H=1, mg_mgr_init() also calls mg_tcpip_init(). // If no driver is selected, automatic driver init is disabled, or multiple // interfaces are intended, call mg_tcpip_init() separately. 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 data and appends it to a connection send buffer. // // Returns: // Number of bytes appended, or 0 on OOM. // Example: // mg_printf(c, "GET / HTTP/1.0\r\nHost: %.*s\r\n\r\n", // (int) host.len, host.buf); // Full examples: // tutorials/http/http-client, tutorials/http/http-proxy-client, // tutorials/http/http-restful-server // Related APIs: // mg_send(), mg_snprintf(), mg_http_reply(), mg_ws_printf() // Notes: // Data is sent asynchronously by a later mg_mgr_poll() call. Supports // mg_xprintf specifiers, including custom %M/%m printers. See src/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);