Usage Example
--
-
-
-
Copy
-mongoose.candmongoose.hto your build tree
- -
-
Write code that uses Mongoose API, e.g. in
-my_app.c
- -
-
Compile application:
-$ cc my_app.c mongoose.c
-
#include "mongoose.h"
-
-static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
- struct mbuf *io = &nc->recv_mbuf;
-
- switch (ev) {
- case MG_EV_RECV:
- // This event handler implements simple TCP echo server
- mg_send(nc, io->buf, io->len); // Echo received data back
- mbuf_remove(io, io->len); // Discard data from recv buffer
- break;
- default:
- break;
- }
-}
-
-int main(void) {
- struct mg_mgr mgr;
-
- mg_mgr_init(&mgr, NULL);
-
- // Note that many connections can be added to a single event manager
- // Connections can be created at any point, e.g. in event handler function
- mg_bind(&mgr, "1234", ev_handler);
-
- for (;;) {
- mg_mgr_poll(&mgr, 1000);
- }
-
- mg_mgr_free(&mgr);
- return 0;
-}
-| Include Mongoose API definitions | -|
| Define an event handler function | -|
| Initialize event manager object | -|
| Create listening connection and add it to the event manager | -|
| Start infinite event loop | -
Design Concept
-Mongoose is a multi-protocol networking library that implements non-blocking, -asyncronous IO and provides event-based API. It has three basic data structures:
--
-
-
-
-struct mg_mgris an event manager -that holds all active connections
- -
-
-struct mg_connectiondescribes a connection
- -
-
-struct mbufdescribes data buffer -(received or sent data)
-
Connections could be either listening, outbound or inbound.
-Outbound connections are created by mg_connect() call.
-Listening connections are created by mg_bind() call.
-Inbound connections are those accepted by a listening connection.
-Each connection is described by
-struct mg_connection structure, which has
-a number of fields like socket, event handler function, send/receive buffer,
-flags, et cetera.
Mongoose usage pattern is to declare and initialize event manager, create
-connections and create an event loop by calling
-mg_mgr_poll() in a loop.
-mg_mgr_poll() iterates over all sockets,
-accepts new connections, sends and receives data, closes connections,
-and calls event handler functions for the respective events.
Memory buffers
-Each connection has send and receive buffer,
-struct mg_connection::send_mbuf
-and
-struct mg_connection::recv_mbuf respectively.
-When data arrives,
-Mongoose appends received data to the recv_mbuf and
-triggers MG_EV_RECV event. User may send data back by calling one of the
-output functions, like mg_send() or
-mg_printf(). Output functions append data to the
-send_mbuf. When Mongoose
-successfully writes data to the socket, it discards data from
-mg_connection::send_mbuf and
-sends MG_EV_SEND event. When connection is closed, MG_EV_CLOSE event is sent.
-Event handler function
-Each connection has an event handler function associated with it. That -function must be implemented by user. Event handler is the key element of -the Mongoose application, since it defines application’s behavior. This is how -an event handler function looks like:
-static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
- switch (ev) {
- /* Event handler code that defines behavior of the connection */
- ...
- }
-}
--
-
- struct mg_connection *nc -
-
-
Connection that has received an event.
-
- - int ev -
-
-
Event number, defined in
-mongoose.h. For example, when data arrives -on inbound connectionevwould beMG_EV_RECV.
- - void *ev_data -
-
-
This pointer points to the event-specific data, and it has different -meaning for different events. For example, for
-MG_EV_RECVevent, -ev_datais anint *pointer, pointing to the number of bytes received -from the remote peer and saved into the receive IO buffer. Exact meaning -ofev_datais described for each event. Protocol-specific events usually -haveev_datapointing to structures that hold protocol-specific information.
-
|
- |
-
-struct mg_connection has void *user_data
-which is a placeholder for a application-specific data. Mongoose does not use
-that pointer. Event handler can store any kind of information there.
- |
-
Events
-Mongoose accepts incoming connections, reads and writes data, and -calls specified event handler for each connection when appropriate. Typical -event sequence is this:
--
-
-
-
For outbound connection:
-MG_EV_CONNECT→ (MG_EV_RECV,MG_EV_SEND,MG_EV_POLL…) →MG_EV_CLOSE
- -
-
For inbound connection:
-MG_EV_ACCEPT→ (MG_EV_RECV,MG_EV_SEND,MG_EV_POLL…) →MG_EV_CLOSE
-
Below is a list -of core events triggered by Mongoose (note that each protocol triggers -protocol-specific events in addition to the core ones):
--
-
- MG_EV_ACCEPT -
-
-
sent when new server connection is accepted by a -listening connection.
-void *ev_dataisunion socket_address-of the remote peer.
- - MG_EV_CONNECT -
-
-
sent when a new outbound connection created by -
-mg_connect()-either failed or succeeded.void *ev_dataisint *success. -Ifsuccessis 0, then connection has been established, -otherwise it contains error code. See -mg_connect_opt()function for code example.
- - MG_EV_RECV -
-
-
New data is received and appended to the end of
-recv_mbuf. -void *ev_dataisint *num_received_bytes. Typically, event handler -should check received data innc→recv_mbuf, -discard processed data by callingmbuf_remove(), -set connection flagsnc→flagsif necessary -(seestruct mg_connection), and write -data the remote peer by output functions likemg_send().
-
|
- |
-
-Mongoose uses realloc() to expand receive buffer.
-It is user’s responsibility to discard processed
-data from the beginning of receive buffer, note the mbuf_remove()
-call in the example above.
- |
-
-
-
- MG_EV_SEND -
-
-
Mongoose has written data to the remote peer and discarded -written data from the -
-mg_connection::send_mbuf.void *ev_data-isint *num_sent_bytes.
-
|
- |
-
-Mongoose output functions only append
-data to the mg_connection::send_mbuf, they do not do any socket writes.
-An actual IO is done by mg_mgr_poll(). MG_EV_SEND event
-is just a notification about an IO has been done.
- |
-
-
-
- MG_EV_POLL -
-
-
Sent to all connections on each invocation of -
-mg_mgr_poll(). -This event could be used to do any housekeeping, for example check whether -certain timeout has expired and close the connection, or send heartbeet -message, et cetera.
- - MG_EV_TIMER -
-
-
Sent to the connection if -
-mg_set_timer()was called.
-
Connection flags
-Each connection has a flags bit field. Some flags are set by Mongoose, for
-example if a user creates an outbound UDP connection using udp://1.2.3.4:5678
-address, Mongoose is going to set MG_F_UDP flag for that connection. Other flags
-are meant to be set only by user event handler to tell Mongoose how to behave.
-Below is a list of connection flags that are meant to be set by event handlers:
-
-
-
-
-MG_F_FINISHED_SENDING_DATAtells Mongoose that all data has been -appended to thesend_mbuf. As soon as Mongoose sends it to the -socket, the connection will be closed.
- -
-
-MG_F_BUFFER_BUT_DONT_SENDtells Mongoose to append data to the -send_mbufbut hold on sending it, because the data will be modified -later and then will be sent by clearingMG_F_BUFFER_BUT_DONT_SENDflag.
- -
-
-MG_F_CLOSE_IMMEDIATELYtells Mongoose to close the connection -immediately, usually after some error
- -
-
-MG_F_USER_1,MG_F_USER_2,MG_F_USER_3,MG_F_USER_4could be -used by a developer to store application-specific state
-
Flags below are set by Mongoose:
--
-
-
-
-MG_F_SSL_HANDSHAKE_DONESSL only, set when SSL handshake is done.
- -
-
-MG_F_CONNECTINGset when connection is in connecting state after -mg_connect()call but connect did not finish yet.
- -
-
-MG_F_LISTENINGset for all listening connections
- -
-
-MG_F_UDPset if connection is UDP
- -
-
-MG_F_IS_WEBSOCKETset if connection is a Websocket connection
- -
-
-MG_F_WEBSOCKET_NO_DEFRAGshould be set by a user if user wants to switch -off automatic Websocket frame defragmentation
-
Build Options
-Mongoose source code ships in a single .c file that contains functionality -for all supported protocols (modules). Modules can be disabled at compile -time which reduces executable size. That can be done by setting preprocessor -flags. Also, some preprocessor flags can be used to tune internal Mongoose -parameters.
-To set a preprocessor flag during compile time, use -D <PREPROCESSOR_FLAG>
-compiler option. For example, to disable both MQTT and JSON-RPC,
-compile the application my_app.c like this (assumed UNIX system):
$ cc my_app.c mongoose.c -D MG_DISABLE_MQTT -D MG_DISABLE_JSON_RPC
-Enabling flags
--
-
-
-
-MG_ENABLE_SSLEnable OpenSSL support
- -
-
-MG_ENABLE_IPV6Enable IPV6 support
- -
-
-MG_ENABLE_THREADSenablemg_start_thread()API
- -
-
-MG_ENABLE_MQTT_BROKERenable MQTT broker
- -
-
-MG_ENABLE_DNS_SERVERenable DNS server
- -
-
-MG_ENABLE_COAPenable CoAP protocol
- -
-
-MG_ENABLE_GETADDRINFOenablegetaddrinfo()inmg_resolve2()
-
Disabling flags
--
-
-
-
-MG_DISABLE_HTTP_WEBSOCKETdisable HTTP + Websocket protocol support
- -
-
-MG_DISABLE_HTTP_DIGEST_AUTHdisable HTTP Digest (MD5) authorization support
- -
-
-MG_DISABLE_MQTTdisable MQTT support
- -
-
-MG_DISABLE_SHA1disable SHA1 support (used by Websocket)
- -
-
-MG_DISABLE_MD5disable MD5 support (used by HTTP auth)
- -
-
-MG_DISABLE_JSON_RPCdisable JSON-RPC support
- -
-
-MG_DISABLE_SOCKETPAIRdisablemg_broadcast()API
- -
-
-MG_DISABLE_HTTP_KEEP_ALIVEuseful for embedded systems to save resources
-
Platform specific
-Mongoose tries to detect the target platform whenever possible, but in some cases you have -to explicitly declare some peculiarities of your target, such as:
--
-
-
-
-MG_LWIP: use LWIP networking stack
- -
-
-MG_CC3200: enable workarounds for the TI CC3200 target.
- -
-
-MG_ESP8266: enable workarounds for the ESP8266 target, addRTOS_SDKto specify the RTOS SDK flavour.
-
Tunables
--
-
-
-
-MG_MALLOC,MG_CALLOC,MG_REALLOC,MG_FREEallow to use custom -memory allocator, e.g.-DMG_MALLOC=my_malloc
- -
-
-MG_USE_READ_WRITEwhen set replaces calls torecvwithreadandsendwithwrite, -thus enabling to add any kind of file descriptor (files, serial devices) to an event manager.
- -
-
-MG_SSL_CRYPTO_MODERN,MG_SSL_CRYPTO_OLD- choose either "Modern" or "Old" ciphers -instead of the default "Intermediate" setting. -See [this article](https://wiki.mozilla.org/Security/Server_Side_TLS#Recommended_configurations) for details.
-
API Reference
-Memory Buffers
-Mbufs are mutable/growing memory buffers, like C++ strings. -Mbuf can append data to the end of a buffer, or insert data into arbitrary -position in the middle of a buffer. The buffer grows automatically when -needed.
-struct mbuf
-struct mbuf {
- char *buf; /* Buffer pointer */
- size_t len; /* Data length. Data is located between offset 0 and len. */
- size_t size; /* Buffer size allocated by realloc(1). Must be >= len */
-};
-Memory buffer descriptor
-mbuf_init()
-void mbuf_init(struct mbuf *, size_t initial_capacity);
-Initialize an Mbuf.
-initial_capacity specifies the initial capacity of the mbuf.
mbuf_free()
-void mbuf_free(struct mbuf *);
-Free the space allocated for the mbuffer and resets the mbuf structure.
-mbuf_append()
-size_t mbuf_append(struct mbuf *, const void *data, size_t data_size);
-Appends data to the Mbuf.
-Return the number of bytes appended, or 0 if out of memory.
-mbuf_insert()
-size_t mbuf_insert(struct mbuf *, size_t, const void *, size_t);
-Insert data at a specified offset in the Mbuf.
-Existing data will be shifted forwards and the buffer will -be grown if necessary. -Return the number of bytes inserted.
-mbuf_remove()
-void mbuf_remove(struct mbuf *, size_t data_size);
-Remove data_size bytes from the beginning of the buffer.
mbuf_resize()
-void mbuf_resize(struct mbuf *, size_t new_size);
-Resize an Mbuf.
-If new_size is smaller than buffer’s len, the
-resize is not performed.
mbuf_trim()
-void mbuf_trim(struct mbuf *);
-Shrink an Mbuf by resizing its size to len.
Core: TCP/UDP/SSL
-|
- |
-
-Mongoose manager is single threaded. It does not protect
-its data structures by mutexes, therefore all functions that are dealing
-with particular event manager should be called from the same thread,
-with exception of mg_broadcast() function. It is fine to have different
-event managers handled by different threads.
- |
-
struct mg_str
-struct mg_str {
- const char *p; /* Memory chunk pointer */
- size_t len; /* Memory chunk length */
-};
-Describes chunk of memory
-struct mg_mgr
-struct mg_mgr {
- struct mg_connection *active_connections;
- const char *hexdump_file; /* Debug hexdump file path */
-#ifndef MG_DISABLE_SOCKETPAIR
- sock_t ctl[2]; /* Socketpair for mg_wakeup() */
-#endif
- void *user_data; /* User data */
- void *mgr_data; /* Implementation-specific event manager's data. */
-#ifdef MG_ENABLE_JAVASCRIPT
- struct v7 *v7;
-#endif
-};
-Mongoose event manager.
-struct mg_connection
-struct mg_connection {
- struct mg_connection *next, *prev; /* mg_mgr::active_connections linkage */
- struct mg_connection *listener; /* Set only for accept()-ed connections */
- struct mg_mgr *mgr; /* Pointer to containing manager */
-
- sock_t sock; /* Socket to the remote peer */
- int err;
- union socket_address sa; /* Remote peer address */
- size_t recv_mbuf_limit; /* Max size of recv buffer */
- struct mbuf recv_mbuf; /* Received data */
- struct mbuf send_mbuf; /* Data scheduled for sending */
- SSL *ssl;
- SSL_CTX *ssl_ctx;
- time_t last_io_time; /* Timestamp of the last socket IO */
- double ev_timer_time; /* Timestamp of the future MG_EV_TIMER */
- mg_event_handler_t proto_handler; /* Protocol-specific event handler */
- void *proto_data; /* Protocol-specific data */
- void (*proto_data_destructor)(void *proto_data);
- mg_event_handler_t handler; /* Event handler function */
- void *user_data; /* User-specific data */
- union {
- void *v;
- /*
- * the C standard is fussy about fitting function pointers into
- * void pointers, since some archs might have fat pointers for functions.
- */
- mg_event_handler_t f;
- } priv_1; /* Used by mg_enable_multithreading() */
- void *priv_2; /* Used by mg_enable_multithreading() */
- void *mgr_data; /* Implementation-specific event manager's data. */
- unsigned long flags;
-/* Flags set by Mongoose */
-#define MG_F_LISTENING (1 << 0) /* This connection is listening */
-#define MG_F_UDP (1 << 1) /* This connection is UDP */
-#define MG_F_RESOLVING (1 << 2) /* Waiting for async resolver */
-#define MG_F_CONNECTING (1 << 3) /* connect() call in progress */
-#define MG_F_SSL_HANDSHAKE_DONE (1 << 4) /* SSL specific */
-#define MG_F_WANT_READ (1 << 5) /* SSL specific */
-#define MG_F_WANT_WRITE (1 << 6) /* SSL specific */
-#define MG_F_IS_WEBSOCKET (1 << 7) /* Websocket specific */
-
-/* Flags that are settable by user */
-#define MG_F_SEND_AND_CLOSE (1 << 10) /* Push remaining data and close */
-#define MG_F_CLOSE_IMMEDIATELY (1 << 11) /* Disconnect */
-#define MG_F_WEBSOCKET_NO_DEFRAG (1 << 12) /* Websocket specific */
-#define MG_F_DELETE_CHUNK (1 << 13) /* HTTP specific */
-
-#define MG_F_USER_1 (1 << 20) /* Flags left for application */
-#define MG_F_USER_2 (1 << 21)
-#define MG_F_USER_3 (1 << 22)
-#define MG_F_USER_4 (1 << 23)
-#define MG_F_USER_5 (1 << 24)
-#define MG_F_USER_6 (1 << 25)
-};
-Mongoose connection.
-struct mg_add_sock_opts
-struct mg_add_sock_opts {
- void *user_data; /* Initial value for connection's user_data */
- unsigned int flags; /* Initial connection flags */
- const char **error_string; /* Placeholder for the error string */
-};
-Optional parameters to mg_add_sock_opt().
flags is an initial struct mg_connection::flags bitmask to set,
-see MG_F_* flags definitions.
struct mg_bind_opts
-struct mg_bind_opts {
- void *user_data; /* Initial value for connection's user_data */
- unsigned int flags; /* Extra connection flags */
- const char **error_string; /* Placeholder for the error string */
-#ifdef MG_ENABLE_SSL
- /* SSL settings. */
- const char *ssl_cert; /* Server certificate to present to clients */
- const char *ssl_ca_cert; /* Verify client certificates with this CA bundle */
-#endif
-};
-Optional parameters to mg_bind_opt().
flags is an initial struct mg_connection::flags bitmask to set,
-see MG_F_* flags definitions.
struct mg_connect_opts
-struct mg_connect_opts {
- void *user_data; /* Initial value for connection's user_data */
- unsigned int flags; /* Extra connection flags */
- const char **error_string; /* Placeholder for the error string */
-#ifdef MG_ENABLE_SSL
- /* SSL settings. */
- const char *ssl_cert; /* Client certificate to present to the server */
- const char *ssl_ca_cert; /* Verify server certificate using this CA bundle */
-
- /*
- * Server name verification. If ssl_ca_cert is set and the certificate has
- * passed verification, its subject will be verified against this string.
- * By default (if ssl_server_name is NULL) hostname part of the address will
- * be used. Wildcard matching is supported. A special value of "*" disables
- * name verification.
- */
- const char *ssl_server_name;
-#endif
-};
-Optional parameters to mg_connect_opt()
mg_mgr_init()
-void mg_mgr_init(struct mg_mgr *mgr, void *user_data);
-Initialize Mongoose manager. Side effect: ignores SIGPIPE signal.
-mgr→user_data field will be initialized with user_data parameter.
-That is an arbitrary pointer, where user code can associate some data
-with the particular Mongoose manager. For example, a C++ wrapper class
-could be written, in which case user_data can hold a pointer to the
-class instance.
mg_mgr_free()
-void mg_mgr_free(struct mg_mgr *);
-De-initializes Mongoose manager.
-Close and deallocate all active connections.
-mg_mgr_poll()
-time_t mg_mgr_poll(struct mg_mgr *, int milli);
-This function performs the actual IO, and must be called in a loop
-(an event loop). Returns the current timestamp.
-milli is the maximum number of milliseconds to sleep.
-mg_mgr_poll() checks all connection for IO readiness. If at least one
-of the connections is IO-ready, mg_mgr_poll() triggers respective
-event handlers and returns.
mg_broadcast()
-void mg_broadcast(struct mg_mgr *, mg_event_handler_t func, void *, size_t);
-Pass a message of a given length to all connections.
-Must be called from a thread that does NOT call mg_mgr_poll().
-Note that mg_broadcast() is the only function
-that can be, and must be, called from a different (non-IO) thread.
func callback function will be called by the IO thread for each
-connection. When called, event would be MG_EV_POLL, and message will
-be passed as ev_data pointer. Maximum message size is capped
-by MG_CTL_MSG_MESSAGE_SIZE which is set to 8192 bytes.
mg_next()
-struct mg_connection *mg_next(struct mg_mgr *, struct mg_connection *);
-Iterate over all active connections.
-Returns next connection from the list
-of active connections, or NULL if there is no more connections. Below
-is the iteration idiom:
for (c = mg_next(srv, NULL); c != NULL; c = mg_next(srv, c)) {
- // Do something with connection `c`
-}
-mg_add_sock()
-struct mg_connection *mg_add_sock(struct mg_mgr *, sock_t, mg_event_handler_t);
-Create a connection, associate it with the given socket and event handler, -and add it to the manager.
-For more options see the mg_add_sock_opt variant.
mg_add_sock_opt()
-struct mg_connection *mg_add_sock_opt(struct mg_mgr *, sock_t,
- mg_event_handler_t,
- struct mg_add_sock_opts);
-Create a connection, associate it with the given socket and event handler, -and add to the manager.
-See the mg_add_sock_opts structure for a description of the options.
mg_bind()
-struct mg_connection *mg_bind(struct mg_mgr *, const char *,
- mg_event_handler_t);
-Create listening connection.
-See mg_bind_opt for full documentation.
mg_bind_opt()
-struct mg_connection *mg_bind_opt(struct mg_mgr *mgr, const char *address,
- mg_event_handler_t handler,
- struct mg_bind_opts opts);
-Create listening connection.
-address parameter tells which address to bind to. It’s format is the same
-as for the mg_connect() call, where HOST part is optional. address
-can be just a port number, e.g. :8000. To bind to a specific interface,
-an IP address can be specified, e.g. 1.2.3.4:8000. By default, a TCP
-connection is created. To create UDP connection, prepend udp:// prefix,
-e.g. udp://:8000. To summarize, address paramer has following format:
-[PROTO://][IP_ADDRESS]:PORT, where PROTO could be tcp or udp.
See the mg_bind_opts structure for a description of the optional
-parameters.
Return a new listening connection, or NULL on error.
-NOTE: Connection remains owned by the manager, do not free().
mg_connect()
-struct mg_connection *mg_connect(struct mg_mgr *mgr, const char *address,
- mg_event_handler_t handler);
-Connect to a remote host.
-See mg_connect_opt() for full documentation.
mg_connect_opt()
-struct mg_connection *mg_connect_opt(struct mg_mgr *mgr, const char *address,
- mg_event_handler_t handler,
- struct mg_connect_opts opts);
-Connect to a remote host.
-address format is [PROTO://]HOST:PORT. PROTO could be tcp or udp.
-HOST could be an IP address,
-IPv6 address (if Mongoose is compiled with -DMG_ENABLE_IPV6), or a host
-name. If HOST is a name, Mongoose will resolve it asynchronously. Examples
-of valid addresses: google.com:80, udp://1.2.3.4:53, 10.0.0.1:443,
-[::1]:80
See the mg_connect_opts structure for a description of the optional
-parameters.
Returns a new outbound connection, or NULL on error.
|
- |
--Connection remains owned by the manager, do not free(). - | -
|
- |
-
-To enable IPv6 addresses, -DMG_ENABLE_IPV6 should be specified
-in the compilation flags.
- |
-
|
- |
-
-New connection will receive MG_EV_CONNECT as it’s first event
-which will report connect success status.
-If asynchronous resolution fail, or connect() syscall fail for whatever
-reason (e.g. with ECONNREFUSED or ENETUNREACH), then MG_EV_CONNECT
-event report failure. Code example below:
- |
-
static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
- int connect_status;
-
- switch (ev) {
- case MG_EV_CONNECT:
- connect_status = * (int *) ev_data;
- if (connect_status == 0) {
- // Success
- } else {
- // Error
- printf("connect() error: %s\n", strerror(connect_status));
- }
- break;
- ...
- }
-}
-
- ...
- mg_connect(mgr, "my_site.com:80", ev_handler);
-mg_set_ssl()
-const char *mg_set_ssl(struct mg_connection *nc, const char *cert,
- const char *ca_cert);
-Enable SSL for a given connection.
-cert is a server certificate file name for a listening connection,
-or a client certificate file name for an outgoing connection.
-Certificate files must be in PEM format. Server certificate file
-must contain a certificate, concatenated with a private key, optionally
-concatenated with parameters.
-ca_cert is a CA certificate, or NULL if peer verification is not
-required.
-Return: NULL on success, or error message on error.
mg_send()
-void mg_send(struct mg_connection *, const void *buf, int len);
-Send data to the connection.
-Note that sending functions do not actually push data to the socket. -They just append data to the output buffer. MG_EV_SEND will be delivered when -the data has actually been pushed out.
-mg_printf()
-int mg_printf(struct mg_connection *, const char *fmt, ...);
-Send printf-style formatted data to the connection.
See mg_send for more details on send semantics.
mg_vprintf()
-int mg_vprintf(struct mg_connection *, const char *fmt, va_list ap);
-Same as mg_printf(), but takes va_list ap as an argument.
mg_socketpair()
-int mg_socketpair(sock_t[2], int sock_type);
-Create a socket pair.
-sock_type can be either SOCK_STREAM or SOCK_DGRAM.
-Return 0 on failure, 1 on success.
mg_check_ip_acl()
-int mg_check_ip_acl(const char *acl, uint32_t remote_ip);
-Verify given IP address against the ACL.
-remote_ip - an IPv4 address to check, in host byte order
-acl - a comma separated list of IP subnets: x.x.x.x/x or x.x.x.x.
-Each subnet is
-prepended by either a - or a + sign. A plus sign means allow, where a
-minus sign means deny. If a subnet mask is omitted, such as -1.2.3.4,
-this means to deny only that single IP address.
-Subnet masks may vary from 0 to 32, inclusive. The default setting
-is to allow all accesses. On each request the full list is traversed,
-and the last match wins. Example:
-0.0.0.0/0,+192.168/16 - deny all acccesses, only allow 192.168/16 subnet
To learn more about subnet masks, see the -Wikipedia page on Subnetwork
-Return -1 if ACL is malformed, 0 if address is disallowed, 1 if allowed.
-mg_enable_multithreading()
-void mg_enable_multithreading(struct mg_connection *nc);
-Enable multi-threaded handling for the given listening connection nc.
-For each accepted connection, Mongoose will create a separate thread
-and run event handler in that thread. Thus, if an event hanler is doing
-a blocking call or some long computation, that will not slow down
-other connections.
mg_enable_javascript()
-enum v7_err mg_enable_javascript(struct mg_mgr *m, struct v7 *v7,
- const char *init_js_file_name);
-Enable server-side JavaScript scripting.
-Requires -DMG_ENABLE_JAVASCRIPT compilation flag, and V7 engine sources.
-v7 instance must not be destroyed during manager’s lifetime.
-Return V7 error.
mg_set_timer()
-double mg_set_timer(struct mg_connection *c, double timestamp);
-Schedule MG_EV_TIMER event to be delivered at timestamp time.
-timestamp is a UNIX time (a number of seconds since Epoch). It is
-double instead of time_t to allow for sub-second precision.
-Return the old timer value.
Example: set connect timeout to 1.5 seconds:
- c = mg_connect(&mgr, "cesanta.com", ev_handler);
- mg_set_timer(c, mg_time() + 1.5);
- ...
-
- void ev_handler(struct mg_connection *c, int ev, void *ev_data) {
- switch (ev) {
- case MG_EV_CONNECT:
- mg_set_timer(c, 0); // Clear connect timer
- break;
- case MG_EV_TIMER:
- log("Connect timeout");
- c->flags |= MG_F_CLOSE_IMMEDIATELY;
- break;
-mg_time()
-double mg_time();
-A sub-second precision version of time().
-HTTP + Websocket
-struct http_message
-struct http_message {
- struct mg_str message; /* Whole message: request line + headers + body */
-
- /* HTTP Request line (or HTTP response line) */
- struct mg_str method; /* "GET" */
- struct mg_str uri; /* "/my_file.html" */
- struct mg_str proto; /* "HTTP/1.1" -- for both request and response */
-
- /* For responses, code and response status message are set */
- int resp_code;
- struct mg_str resp_status_msg;
-
- /*
- * Query-string part of the URI. For example, for HTTP request
- * GET /foo/bar?param1=val1¶m2=val2
- * | uri | query_string |
- *
- * Note that question mark character doesn't belong neither to the uri,
- * nor to the query_string
- */
- struct mg_str query_string;
-
- /* Headers */
- struct mg_str header_names[MG_MAX_HTTP_HEADERS];
- struct mg_str header_values[MG_MAX_HTTP_HEADERS];
-
- /* Message body */
- struct mg_str body; /* Zero-length for requests with no body */
-};
-HTTP message
-struct websocket_message
-struct websocket_message {
- unsigned char *data;
- size_t size;
- unsigned char flags;
-};
-WebSocket message
-struct mg_http_multipart_part
-struct mg_http_multipart_part {
- const char *file_name;
- const char *var_name;
- struct mg_str data;
- int status; /* <0 on error */
- void *user_data;
-};
-HTTP multipart part
-struct mg_serve_http_opts
-struct mg_serve_http_opts {
- /* Path to web root directory */
- const char *document_root;
-
- /* List of index files. Default is "" */
- const char *index_files;
-
- /*
- * Leave as NULL to disable authentication.
- * To enable directory protection with authentication, set this to ".htpasswd"
- * Then, creating ".htpasswd" file in any directory automatically protects
- * it with digest authentication.
- * Use `mongoose` web server binary, or `htdigest` Apache utility to
- * create/manipulate passwords file.
- * Make sure `auth_domain` is set to a valid domain name.
- */
- const char *per_directory_auth_file;
-
- /* Authorization domain (domain name of this web server) */
- const char *auth_domain;
-
- /*
- * Leave as NULL to disable authentication.
- * Normally, only selected directories in the document root are protected.
- * If absolutely every access to the web server needs to be authenticated,
- * regardless of the URI, set this option to the path to the passwords file.
- * Format of that file is the same as ".htpasswd" file. Make sure that file
- * is located outside document root to prevent people fetching it.
- */
- const char *global_auth_file;
-
- /* Set to "no" to disable directory listing. Enabled by default. */
- const char *enable_directory_listing;
-
- /* SSI files pattern. If not set, "**.shtml$|**.shtm$" is used. */
- const char *ssi_pattern;
-
- /* IP ACL. By default, NULL, meaning all IPs are allowed to connect */
- const char *ip_acl;
-
- /* URL rewrites.
- *
- * Comma-separated list of `uri_pattern=file_or_directory_path` rewrites.
- * When HTTP request is received, Mongoose constructs a file name from the
- * requested URI by combining `document_root` and the URI. However, if the
- * rewrite option is used and `uri_pattern` matches requested URI, then
- * `document_root` is ignored. Instead, `file_or_directory_path` is used,
- * which should be a full path name or a path relative to the web server's
- * current working directory. Note that `uri_pattern`, as all Mongoose
- * patterns, is a prefix pattern.
- *
- * If uri_pattern starts with `@` symbol, then Mongoose compares it with the
- * HOST header of the request. If they are equal, Mongoose sets document root
- * to `file_or_directory_path`, implementing virtual hosts support.
- * Example: `@foo.com=/document/root/for/foo.com`
- *
- * If `uri_pattern` starts with `%` symbol, then Mongoose compares it with
- * the listening port. If they match, then Mongoose issues a 301 redirect.
- * For example, to redirect all HTTP requests to the
- * HTTPS port, do `%80=https://my.site.com`. Note that the request URI is
- * automatically appended to the redirect location.
- */
- const char *url_rewrites;
-
- /* DAV document root. If NULL, DAV requests are going to fail. */
- const char *dav_document_root;
-
- /*
- * DAV passwords file. If NULL, DAV requests are going to fail.
- * If passwords file is set to "-", then DAV auth is disabled.
- */
- const char *dav_auth_file;
-
- /* Glob pattern for the files to hide. */
- const char *hidden_file_pattern;
-
- /* Set to non-NULL to enable CGI, e.g. **.cgi$|**.php$" */
- const char *cgi_file_pattern;
-
- /* If not NULL, ignore CGI script hashbang and use this interpreter */
- const char *cgi_interpreter;
-
- /*
- * Comma-separated list of Content-Type overrides for path suffixes, e.g.
- * ".txt=text/plain; charset=utf-8,.c=text/plain"
- */
- const char *custom_mime_types;
-
- /*
- * Extra HTTP headers to add to each server response.
- * Example: to enable CORS, set this to "Access-Control-Allow-Origin: *".
- */
- const char *extra_headers;
-};
-This structure defines how mg_serve_http() works.
-Best practice is to set only required settings, and leave the rest as NULL.
mg_set_protocol_http_websocket()
-void mg_set_protocol_http_websocket(struct mg_connection *nc);
-Attach built-in HTTP event handler to the given connection. -User-defined event handler will receive following extra events:
--
-
-
-
MG_EV_HTTP_REQUEST: HTTP request has arrived. Parsed HTTP request -is passed as -
-struct http_messagethrough the handler’svoid *ev_datapointer.
- -
-
MG_EV_HTTP_MULTIPART_REQUEST: A multipart POST request has received. -This event is sent before body is parsed. After this user -should expect a sequence of MG_EV_HTTP_PART_BEGIN/DATA/END requests. -This is also the last time when headers and other request fields are -accessible.
-
- -
-
MG_EV_HTTP_REPLY: HTTP reply has arrived. Parsed HTTP reply is passed as -
-struct http_messagethrough the handler’svoid *ev_datapointer.
- -
-
MG_EV_HTTP_CHUNK: HTTP chunked-encoding chunk has arrived. -Parsed HTTP reply is passed as
-struct http_messagethrough the -handler’svoid *ev_datapointer.http_message::bodywould contain -incomplete, reassembled HTTP body. -It will grow with every new chunk arrived, and -potentially can consume a lot of memory. An event handler may process -the body as chunks are coming, and signal Mongoose to delete processed -body by settingMG_F_DELETE_CHUNKinmg_connection::flags. When -the last zero chunk is received, -Mongoose sendsMG_EV_HTTP_REPLYevent with -full reassembled body (if handler did not signal to delete chunks) or -with empty body (if handler did signal to delete chunks).
- -
-
MG_EV_WEBSOCKET_HANDSHAKE_REQUEST: server has received websocket handshake -request.
-ev_datacontains parsed HTTP request.
- -
-
MG_EV_WEBSOCKET_HANDSHAKE_DONE: server has completed Websocket handshake. -
-ev_dataisNULL.
- -
-
MG_EV_WEBSOCKET_FRAME: new websocket frame has arrived.
-ev_datais -struct websocket_message *
- -
-
MG_EV_HTTP_PART_BEGIN: new part of multipart message is started, -extra parameters are passed in mg_http_multipart_part
-
- -
-
MG_EV_HTTP_PART_DATA: new portion of data from multiparted message -no additional headers are available, only data and data size
-
- -
-
MG_EV_HTTP_PART_END: final boundary received, analogue to maybe used to -find the end of packet -Note: Mongoose should be compiled with MG_ENABLE_HTTP_STREAMING_MULTIPART -to enable MG_EV_HTTP_MULTIPART_REQUEST, MG_EV_HTTP_REQUEST_END, -MG_EV_HTTP_REQUEST_CANCEL, MG_EV_HTTP_PART_BEGIN, MG_EV_HTTP_PART_DATA, -MG_EV_HTTP_PART_END constants
-
-
mg_send_websocket_handshake()
-void mg_send_websocket_handshake(struct mg_connection *nc, const char *uri,
- const char *extra_headers);
-Send websocket handshake to the server.
-nc must be a valid connection, connected to a server. uri is an URI
-to fetch, extra_headers` is extra HTTP headers to send or NULL.
This function is intended to be used by websocket client.
-Note that the Host header is mandatory in HTTP/1.1 and must be
-included in extra_headers. mg_send_websocket_handshake2 offers
-a better API for that.
Deprecated in favour of mg_send_websocket_handshake2
mg_send_websocket_handshake2()
-void mg_send_websocket_handshake2(struct mg_connection *nc, const char *path,
- const char *host, const char *protocol,
- const char *extra_headers);
-Send websocket handshake to the server.
-nc must be a valid connection, connected to a server. uri is an URI
-to fetch, host goes into the Host header, protocol goes into the
-Sec-WebSocket-Proto header (NULL to omit), extra_headers` is extra HTTP
-headers to send or NULL.
This function is intended to be used by websocket client.
-mg_connect_ws()
-struct mg_connection *mg_connect_ws(struct mg_mgr *mgr,
- mg_event_handler_t event_handler,
- const char *url, const char *protocol,
- const char *extra_headers);
-Helper function that creates an outbound WebSocket connection.
-url is a URL to connect to. It must be properly URL-encoded, e.g. have
-no spaces, etc. By default, mg_connect_ws() sends Connection and
-Host headers. extra_headers is an extra HTTP headers to send, e.g.
-"User-Agent: my-app\r\n".
-If protocol is not NULL, then a Sec-WebSocket-Protocol header is sent.
Examples:
- nc1 = mg_connect_ws(mgr, ev_handler_1, "ws://echo.websocket.org", NULL,
- NULL);
- nc2 = mg_connect_ws(mgr, ev_handler_1, "wss://echo.websocket.org", NULL,
- NULL);
- nc3 = mg_connect_ws(mgr, ev_handler_1, "ws://api.cesanta.com",
- "clubby.cesanta.com", NULL);
-mg_connect_ws_opt()
-struct mg_connection *mg_connect_ws_opt(struct mg_mgr *mgr,
- mg_event_handler_t ev_handler,
- struct mg_connect_opts opts,
- const char *url, const char *protocol,
- const char *extra_headers);
-Helper function that creates an outbound WebSocket connection
-Mostly identical to mg_connect_ws, but allows to provide extra parameters -(for example, SSL parameters
-mg_send_websocket_frame()
-void mg_send_websocket_frame(struct mg_connection *nc, int op_and_flags,
- const void *data, size_t data_len);
-Send websocket frame to the remote end.
-op_and_flags specifies frame’s type, one of:
-
-
-
-
WEBSOCKET_OP_CONTINUE
-
- -
-
WEBSOCKET_OP_TEXT
-
- -
-
WEBSOCKET_OP_BINARY
-
- -
-
WEBSOCKET_OP_CLOSE
-
- -
-
WEBSOCKET_OP_PING
-
- -
-
WEBSOCKET_OP_PONG
-
-
Orred with one of the flags:
--
-
-
-
WEBSOCKET_DONT_FIN: Don’t set the FIN flag on the frame to be sent.
-
-
data and data_len contain frame data.
mg_send_websocket_framev()
-void mg_send_websocket_framev(struct mg_connection *nc, int op_and_flags,
- const struct mg_str *strings, int num_strings);
-Send multiple websocket frames.
-Like mg_send_websocket_frame(), but composes a frame from multiple buffers.
mg_printf_websocket_frame()
-void mg_printf_websocket_frame(struct mg_connection *nc, int op_and_flags,
- const char *fmt, ...);
-Send websocket frame to the remote end.
-Like mg_send_websocket_frame(), but allows to create formatted message
-with printf()-like semantics.
mg_send_http_chunk()
-void mg_send_http_chunk(struct mg_connection *nc, const char *buf, size_t len);
-Send buffer buf of size len to the client using chunked HTTP encoding.
-This function first sends buffer size as hex number + newline, then
-buffer itself, then newline. For example,
- mg_send_http_chunk(nc, "foo", 3) whill append 3\r\nfoo\r\n string to
-the nc→send_mbuf output IO buffer.
|
- |
--HTTP header "Transfer-Encoding: chunked" should be sent prior to -using this function. - | -
|
- |
--do not forget to send empty chunk at the end of the response, -to tell the client that everything was sent. Example: - | -
mg_printf_http_chunk(nc, "%s", "my response!");
- mg_send_http_chunk(nc, "", 0); // Tell the client we're finished
-mg_printf_http_chunk()
-void mg_printf_http_chunk(struct mg_connection *nc, const char *fmt, ...);
-Send printf-formatted HTTP chunk.
-Functionality is similar to mg_send_http_chunk().
mg_send_response_line()
-void mg_send_response_line(struct mg_connection *c, int status_code,
- const char *extra_headers);
-Send response status line.
-If extra_headers is not NULL, then extra_headers are also sent
-after the reponse line. extra_headers must NOT end end with new line.
-Example:
mg_send_response_line(nc, 200, "Access-Control-Allow-Origin: *");-
Will result in:
-HTTP/1.1 200 OK\r\n -Access-Control-Allow-Origin: *\r\n-
mg_send_head()
-void mg_send_head(struct mg_connection *n, int status_code,
- int64_t content_length, const char *extra_headers);
-Send response line and headers.
-This function sends response line with the status_code, and automatically
-sends one header: either "Content-Length", or "Transfer-Encoding".
-If content_length is negative, then "Transfer-Encoding: chunked" header
-is sent, otherwise, "Content-Length" header is sent.
|
- |
-
-If Transfer-Encoding is chunked, then message body must be sent
-using mg_send_http_chunk() or mg_printf_http_chunk() functions.
-Otherwise, mg_send() or mg_printf() must be used.
-Extra headers could be set through extra_headers - and note extra_headers
-must NOT be terminated by a new line.
- |
-
mg_printf_html_escape()
-void mg_printf_html_escape(struct mg_connection *nc, const char *fmt, ...);
-Send printf-formatted HTTP chunk, escaping HTML tags.
-mg_parse_http()
-int mg_parse_http(const char *s, int n, struct http_message *hm, int is_req);
-Parse a HTTP message.
-is_req should be set to 1 if parsing request, 0 if reply.
Return number of bytes parsed. If HTTP message is
-incomplete, 0 is returned. On parse error, negative number is returned.
mg_get_http_header()
-struct mg_str *mg_get_http_header(struct http_message *hm, const char *name);
-Search and return header name in parsed HTTP message hm.
-If header is not found, NULL is returned. Example:
struct mg_str *host_hdr = mg_get_http_header(hm, "Host");-
mg_http_parse_header()
-int mg_http_parse_header(struct mg_str *hdr, const char *var_name, char *buf,
- size_t buf_size);
-Parse HTTP header hdr. Find variable var_name and store it’s value
-in the buffer buf, buf_size. Return 0 if variable not found, non-zero
-otherwise.
This function is supposed to parse -cookies, authentication headers, etcetera. Example (error handling omitted):
-char user[20]; -struct mg_str *hdr = mg_get_http_header(hm, "Authorization"); -mg_http_parse_header(hdr, "username", user, sizeof(user));-
Return length of the variable’s value. If buffer is not large enough, -or variable not found, 0 is returned.
-mg_parse_multipart()
-size_t mg_parse_multipart(const char *buf, size_t buf_len, char *var_name,
- size_t var_name_len, char *file_name,
- size_t file_name_len, const char **chunk,
- size_t *chunk_len);
-Parse buffer buf, buf_len that contains multipart form data chunks.
-Store chunk name in a var_name, var_name_len buffer.
-If a chunk is an uploaded file, then file_name, file_name_len is
-filled with an uploaded file name. chunk, chunk_len
-points to the chunk data.
Return: number of bytes to skip to the next chunk, or 0 if there are - no more chunks.
-Usage example:
- static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
- switch(ev) {
- case MG_EV_HTTP_REQUEST: {
- struct http_message *hm = (struct http_message *) ev_data;
- char var_name[100], file_name[100];
- const char *chunk;
- size_t chunk_len, n1, n2;
-
- n1 = n2 = 0;
- while ((n2 = mg_parse_multipart(hm->body.p + n1,
- hm->body.len - n1,
- var_name, sizeof(var_name),
- file_name, sizeof(file_name),
- &chunk, &chunk_len)) > 0) {
- printf("var: %s, file_name: %s, size: %d, chunk: [%.*s]\n",
- var_name, file_name, (int) chunk_len,
- (int) chunk_len, chunk);
- n1 += n2;
- }
- }
- break;
-mg_get_http_var()
-int mg_get_http_var(const struct mg_str *buf, const char *name, char *dst,
- size_t dst_len);
-Fetch an HTTP form variable.
-Fetch a variable name from a buf into a buffer specified by
-dst, dst_len. Destination is always zero-terminated. Return length
-of a fetched variable. If not found, 0 is returned. buf must be
-valid url-encoded buffer. If destination is too small, -1 is returned.
mg_url_decode()
-int mg_url_decode(const char *src, int src_len, char *dst, int dst_len,
- int is_form_url_encoded);
-Decode URL-encoded string.
-Source string is specified by (src, src_len), and destination is
-(dst, dst_len). If is_form_url_encoded is non-zero, then
-+ character is decoded as a blank space character. This function
-guarantees to \0-terminate the destination. If destination is too small,
-then source string is partially decoded and -1 is returned. Otherwise,
-a length of decoded string is returned, not counting final \0.
mg_http_create_digest_auth_header()
-int mg_http_create_digest_auth_header(char *buf, size_t buf_len,
- const char *method, const char *uri,
- const char *auth_domain, const char *user,
- const char *passwd);
-Create Digest authentication header for client request.
-mg_connect_http()
-struct mg_connection *mg_connect_http(struct mg_mgr *mgr,
- mg_event_handler_t event_handler,
- const char *url,
- const char *extra_headers,
- const char *post_data);
-Helper function that creates outbound HTTP connection.
-url is a URL to fetch. It must be properly URL-encoded, e.g. have
-no spaces, etc. By default, mg_connect_http() sends Connection and
-Host headers. extra_headers is an extra HTTP headers to send, e.g.
-"User-Agent: my-app\r\n".
-If post_data is NULL, then GET request is created. Otherwise, POST request
-is created with the specified POST data. Note that if the data being posted
-is a form submission, the Content-Type header should be set accordingly
-(see example below).
Examples:
- nc1 = mg_connect_http(mgr, ev_handler_1, "http://www.google.com", NULL,
- NULL);
- nc2 = mg_connect_http(mgr, ev_handler_1, "https://github.com", NULL, NULL);
- nc3 = mg_connect_http(
- mgr, ev_handler_1, "my_server:8000/form_submit/",
- "Content-Type: application/x-www-form-urlencoded\r\n",
- "var_1=value_1&var_2=value_2");
-mg_connect_http_opt()
-struct mg_connection *mg_connect_http_opt(struct mg_mgr *mgr,
- mg_event_handler_t ev_handler,
- struct mg_connect_opts opts,
- const char *url,
- const char *extra_headers,
- const char *post_data);
-Helper function that creates outbound HTTP connection.
-Mostly identical to mg_connect_http, but allows to provide extra parameters -(for example, SSL parameters
-mg_serve_http()
-void mg_serve_http(struct mg_connection *nc, struct http_message *hm,
- struct mg_serve_http_opts opts);
-Serve given HTTP request according to the options.
Example code snippet:
-static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
- struct http_message *hm = (struct http_message *) ev_data;
- struct mg_serve_http_opts opts = { .document_root = "/var/www" }; // C99
-
- switch (ev) {
- case MG_EV_HTTP_REQUEST:
- mg_serve_http(nc, hm, opts);
- break;
- default:
- break;
- }
-}
-mg_register_http_endpoint()
-void mg_register_http_endpoint(struct mg_connection *nc, const char *uri_path,
- mg_event_handler_t handler);
-Register callback for specified http endpoint -Note: if callback is registered it is called instead of -callback provided in mg_bind
-Example code snippet:
-static void handle_hello1(struct mg_connection *nc, int ev, void *ev_data) {
- (void) ev; (void) ev_data;
- mg_printf(nc, "HTTP/1.0 200 OK\r\n\r\n[I am Hello1]");
- nc->flags |= MG_F_SEND_AND_CLOSE;
-}
-
-static void handle_hello1(struct mg_connection *nc, int ev, void *ev_data) {
- (void) ev; (void) ev_data;
- mg_printf(nc, "HTTP/1.0 200 OK\r\n\r\n[I am Hello2]");
- nc->flags |= MG_F_SEND_AND_CLOSE;
-}
-
-void init() {
- nc = mg_bind(&mgr, local_addr, cb1);
- mg_register_http_endpoint(nc, "/hello1", handle_hello1);
- mg_register_http_endpoint(nc, "/hello1/hello2", handle_hello2);
-}
-mg_file_upload_handler()
-void mg_file_upload_handler(struct mg_connection *nc, int ev, void *ev_data,
- mg_fu_fname_fn local_name_fn);
-File upload handler.
-This handler can be used to implement file uploads with minimum code.
-This handler will process MG_EV_HTTP_PART_* events and store file data into
-a local file.
-local_name_fn will be invoked with whatever name was provided by the client
-and will expect the name of the local file to open. Return value of NULL will
-abort file upload (client will get a "403 Forbidden" response). If non-null,
-the returned string must be heap-allocated and will be freed by the caller.
-Exception: it is ok to return the same string verbatim.
Example:
-struct mg_str upload_fname(struct mg_connection *nc, struct mg_str fname) {
- // Just return the same filename. Do not actually do this except in test!
- // fname is user-controlled and needs to be sanitized.
- return fname;
-}
-void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
- switch (ev) {
- ...
- case MG_EV_HTTP_PART_BEGIN:
- case MG_EV_HTTP_PART_DATA:
- case MG_EV_HTTP_PART_END:
- mg_file_upload_handler(nc, ev, ev_data, upload_fname);
- break;
- }
-}
-JSON-RPC
-struct mg_rpc_request
-struct mg_rpc_request {
- struct json_token *message; /* Whole RPC message */
- struct json_token *id; /* Message ID */
- struct json_token *method; /* Method name */
- struct json_token *params; /* Method params */
-};
-JSON-RPC request
-struct mg_rpc_reply
-struct mg_rpc_reply {
- struct json_token *message; /* Whole RPC message */
- struct json_token *id; /* Message ID */
- struct json_token *result; /* Remote call result */
-};
-JSON-RPC response
-struct mg_rpc_error
-struct mg_rpc_error {
- struct json_token *message; /* Whole RPC message */
- struct json_token *id; /* Message ID */
- struct json_token *error_code; /* error.code */
- struct json_token *error_message; /* error.message */
- struct json_token *error_data; /* error.data, can be NULL */
-};
-JSON-RPC error
-mg_rpc_parse_reply()
-int mg_rpc_parse_reply(const char *buf, int len, struct json_token *toks,
- int max_toks, struct mg_rpc_reply *,
- struct mg_rpc_error *);
-Parse JSON-RPC reply contained in buf, len into JSON tokens array
-toks, max_toks. If buffer contains valid reply, reply structure is
-populated. The result of RPC call is located in reply.result. On error,
-error structure is populated. Returns: the result of calling
-parse_json(buf, len, toks, max_toks):
On success, an offset inside json_string is returned
-where parsing has finished. On failure, a negative number is
-returned, one of:
-
-
-
-
-#define JSON_STRING_INVALID -1
- -
-
-#define JSON_STRING_INCOMPLETE -2
- -
-
-#define JSON_TOKEN_ARRAY_TOO_SMALL -3
-
mg_rpc_create_request()
-int mg_rpc_create_request(char *buf, int len, const char *method,
- const char *id, const char *params_fmt, ...);
-Create JSON-RPC request in a given buffer.
-Return length of the request, which
-can be larger then len that indicates an overflow.
-params_fmt format string should conform to json_emit() API,
-see https://github.com/cesanta/frozen
mg_rpc_create_reply()
-int mg_rpc_create_reply(char *buf, int len, const struct mg_rpc_request *req,
- const char *result_fmt, ...);
-Create JSON-RPC reply in a given buffer.
-Return length of the reply, which
-can be larger then len that indicates an overflow.
-result_fmt format string should conform to json_emit() API,
-see https://github.com/cesanta/frozen
mg_rpc_create_error()
-int mg_rpc_create_error(char *buf, int len, struct mg_rpc_request *req,
- int code, const char *message, const char *fmt, ...);
-Create JSON-RPC error reply in a given buffer.
-Return length of the error, which
-can be larger then len that indicates an overflow.
-fmt format string should conform to json_emit() API,
-see https://github.com/cesanta/frozen
mg_rpc_create_std_error()
-int mg_rpc_create_std_error(char *buf, int len, struct mg_rpc_request *req,
- int code);
-Create JSON-RPC error in a given buffer.
-Return length of the error, which
-can be larger then len that indicates an overflow. See
-JSON_RPC_*_ERROR definitions for standard error values:
-
-
-
-
-#define JSON_RPC_PARSE_ERROR (-32700)
- -
-
-#define JSON_RPC_INVALID_REQUEST_ERROR (-32600)
- -
-
-#define JSON_RPC_METHOD_NOT_FOUND_ERROR (-32601)
- -
-
-#define JSON_RPC_INVALID_PARAMS_ERROR (-32602)
- -
-
-#define JSON_RPC_INTERNAL_ERROR (-32603)
- -
-
-#define JSON_RPC_SERVER_ERROR (-32000)
-
mg_rpc_dispatch()
-int mg_rpc_dispatch(const char *buf, int, char *dst, int dst_len,
- const char **methods, mg_rpc_handler_t *handlers);
-Dispatches a JSON-RPC request.
-Parses JSON-RPC request contained in buf, len.
-Then, dispatches the request to the correct handler method.
-Valid method names should be specified in NULL
-terminated array methods, and corresponding handlers in handlers.
-Result is put in dst, dst_len. Return: length of the result, which
-can be larger then dst_len that indicates an overflow.
-Overflown bytes are not written to the buffer.
-If method is not found, an error is automatically generated.
DNS
-struct mg_dns_resource_record
-struct mg_dns_resource_record {
- struct mg_str name; /* buffer with compressed name */
- int rtype;
- int rclass;
- int ttl;
- enum mg_dns_resource_record_kind kind;
- struct mg_str rdata; /* protocol data (can be a compressed name) */
-};
-DNS resource record.
-struct mg_dns_message
-struct mg_dns_message {
- struct mg_str pkt; /* packet body */
- uint16_t flags;
- uint16_t transaction_id;
- int num_questions;
- int num_answers;
- struct mg_dns_resource_record questions[MG_MAX_DNS_QUESTIONS];
- struct mg_dns_resource_record answers[MG_MAX_DNS_ANSWERS];
-};
-DNS message (request and response).
-mg_dns_parse_record_data()
-int mg_dns_parse_record_data(struct mg_dns_message *msg,
- struct mg_dns_resource_record *rr, void *data,
- size_t data_len);
-Parse the record data from a DNS resource record.
--
-
-
-
A: struct in_addr *ina
-
- -
-
AAAA: struct in6_addr *ina
-
- -
-
CNAME: char buffer
-
-
Returns -1 on error.
-TODO(mkm): MX
-mg_send_dns_query()
-void mg_send_dns_query(struct mg_connection *nc, const char *name,
- int query_type);
-Send a DNS query to the remote end.
-mg_dns_insert_header()
-int mg_dns_insert_header(struct mbuf *io, size_t pos,
- struct mg_dns_message *msg);
-Insert a DNS header to an IO buffer.
-Return number of bytes inserted.
-mg_dns_copy_questions()
-int mg_dns_copy_questions(struct mbuf *io, struct mg_dns_message *msg);
-Append already encoded questions from an existing message.
-This is useful when generating a DNS reply message which includes -all question records.
-Return number of appened bytes.
-mg_dns_encode_record()
-int mg_dns_encode_record(struct mbuf *io, struct mg_dns_resource_record *rr,
- const char *name, size_t nlen, const void *rdata,
- size_t rlen);
-Encode and append a DNS resource record to an IO buffer.
-The record metadata is taken from the rr parameter, while the name and data
-are taken from the parameters, encoded in the appropriate format depending on
-record type, and stored in the IO buffer. The encoded values might contain
-offsets within the IO buffer. It’s thus important that the IO buffer doesn’t
-get trimmed while a sequence of records are encoded while preparing a DNS
-*reply.
This function doesn’t update the name and rdata pointers in the rr
-*struct
-because they might be invalidated as soon as the IO buffer grows again.
Return the number of bytes appened or -1 in case of error.
-mg_parse_dns()
-int mg_parse_dns(const char *buf, int len, struct mg_dns_message *msg);
-Low-level: parses a DNS response.
-mg_dns_uncompress_name()
-size_t mg_dns_uncompress_name(struct mg_dns_message *msg, struct mg_str *name,
- char *dst, int dst_len);
-Uncompress a DNS compressed name.
-The containing dns message is required because the compressed encoding -and reference suffixes present elsewhere in the packet.
-If name is less than dst_len characters long, the remainder
-of dst is terminated with \0' characters. Otherwise, `dst is not
-*terminated.
If dst_len is 0 dst can be NULL.
-Return the uncompressed name length.
mg_set_protocol_dns()
-void mg_set_protocol_dns(struct mg_connection *nc);
-Attach built-in DNS event handler to the given listening connection.
-DNS event handler parses incoming UDP packets, treating them as DNS
-requests. If incoming packet gets successfully parsed by the DNS event
-handler, a user event handler will receive MG_DNS_REQUEST event, with
-ev_data pointing to the parsed struct mg_dns_message.
See -[captive_dns_server](https://github.com/cesanta/mongoose/tree/master/examples/captive_dns_server) -example on how to handle DNS request and send DNS reply.
-DNS server
-Disabled by default; enable with -DMG_ENABLE_DNS_SERVER.
mg_dns_create_reply()
-struct mg_dns_reply mg_dns_create_reply(struct mbuf *io,
- struct mg_dns_message *msg);
-Create a DNS reply.
-The reply will be based on an existing query message msg.
-The query body will be appended to the output buffer.
-"reply + recursion allowed" will be added to the message flags and
-message’s num_answers will be set to 0.
Answer records can be appended with mg_dns_send_reply or by lower
-level function defined in the DNS API.
In order to send the reply use mg_dns_send_reply.
-It’s possible to use a connection’s send buffer as reply buffers,
-and it will work for both UDP and TCP connections.
Example:
-reply = mg_dns_create_reply(&nc->send_mbuf, msg);
-for (i = 0; i < msg->num_questions; i++) {
- rr = &msg->questions[i];
- if (rr->rtype == MG_DNS_A_RECORD) {
- mg_dns_reply_record(&reply, rr, 3600, &dummy_ip_addr, 4);
- }
-}
-mg_dns_send_reply(nc, &reply);
-mg_dns_reply_record()
-int mg_dns_reply_record(struct mg_dns_reply *reply,
- struct mg_dns_resource_record *question,
- const char *name, int rtype, int ttl, const void *rdata,
- size_t rdata_len);
-Append a DNS reply record to the IO buffer and to the DNS message.
-The message num_answers field will be incremented. It’s caller’s duty -to ensure num_answers is propertly initialized.
-Returns -1 on error.
-mg_dns_send_reply()
-void mg_dns_send_reply(struct mg_connection *nc, struct mg_dns_reply *r);
-Send a DNS reply through a connection.
-The DNS data is stored in an IO buffer pointed by reply structure in r.
-This function mutates the content of that buffer in order to ensure that
-the DNS header reflects size and flags of the mssage, that might have been
-updated either with mg_dns_reply_record or by direct manipulation of
-r→message.
Once sent, the IO buffer will be trimmed unless the reply IO buffer -is the connection’s send buffer and the connection is not in UDP mode.
-MQTT
-mg_set_protocol_mqtt()
-void mg_set_protocol_mqtt(struct mg_connection *nc);
-Attach built-in MQTT event handler to the given connection.
-The user-defined event handler will receive following extra events:
--
-
-
-
MG_EV_MQTT_CONNACK
-
- -
-
MG_EV_MQTT_PUBLISH
-
- -
-
MG_EV_MQTT_PUBACK
-
- -
-
MG_EV_MQTT_PUBREC
-
- -
-
MG_EV_MQTT_PUBREL
-
- -
-
MG_EV_MQTT_PUBCOMP
-
- -
-
MG_EV_MQTT_SUBACK
-
-
mg_send_mqtt_handshake()
-void mg_send_mqtt_handshake(struct mg_connection *nc, const char *client_id);
-Send MQTT handshake.
-mg_send_mqtt_handshake_opt()
-void mg_send_mqtt_handshake_opt(struct mg_connection *nc, const char *client_id,
- struct mg_send_mqtt_handshake_opts);
-Send MQTT handshake with optional parameters.
-mg_mqtt_publish()
-void mg_mqtt_publish(struct mg_connection *nc, const char *topic,
- uint16_t message_id, int flags, const void *data,
- size_t len);
-Publish a message to a given topic.
-mg_mqtt_subscribe()
-void mg_mqtt_subscribe(struct mg_connection *nc,
- const struct mg_mqtt_topic_expression *topics,
- size_t topics_len, uint16_t message_id);
-Subscribe to a bunch of topics.
-mg_mqtt_unsubscribe()
-void mg_mqtt_unsubscribe(struct mg_connection *nc, char **topics,
- size_t topics_len, uint16_t message_id);
-Unsubscribe from a bunch of topics.
-mg_mqtt_disconnect()
-void mg_mqtt_disconnect(struct mg_connection *nc);
-Send a DISCONNECT command.
-mg_mqtt_connack()
-void mg_mqtt_connack(struct mg_connection *nc, uint8_t return_code);
-Send a CONNACK command with a given return_code.
mg_mqtt_puback()
-void mg_mqtt_puback(struct mg_connection *nc, uint16_t message_id);
-Send a PUBACK command with a given message_id.
mg_mqtt_pubrec()
-void mg_mqtt_pubrec(struct mg_connection *nc, uint16_t message_id);
-Send a PUBREC command with a given message_id.
mg_mqtt_pubrel()
-void mg_mqtt_pubrel(struct mg_connection *nc, uint16_t message_id);
-Send a PUBREL command with a given message_id.
mg_mqtt_pubcomp()
-void mg_mqtt_pubcomp(struct mg_connection *nc, uint16_t message_id);
-Send a PUBCOMP command with a given message_id.
mg_mqtt_suback()
-void mg_mqtt_suback(struct mg_connection *nc, uint8_t *qoss, size_t qoss_len,
- uint16_t message_id);
-Send a SUBACK command with a given message_id
-and a sequence of granted QoSs.
mg_mqtt_unsuback()
-void mg_mqtt_unsuback(struct mg_connection *nc, uint16_t message_id);
-Send a UNSUBACK command with a given message_id.
mg_mqtt_ping()
-void mg_mqtt_ping(struct mg_connection *nc);
-Send a PINGREQ command.
-mg_mqtt_pong()
-void mg_mqtt_pong(struct mg_connection *nc);
-Send a PINGRESP command.
-mg_mqtt_next_subscribe_topic()
-int mg_mqtt_next_subscribe_topic(struct mg_mqtt_message *msg,
- struct mg_str *topic, uint8_t *qos, int pos);
-Extract the next topic expression from a SUBSCRIBE command payload.
-Topic expression name will point to a string in the payload buffer. -Return the pos of the next topic expression or -1 when the list -of topics is exhausted.
-MQTT Broker
-struct mg_mqtt_session
-struct mg_mqtt_session {
- struct mg_mqtt_broker *brk; /* Broker */
- struct mg_mqtt_session *next, *prev; /* mg_mqtt_broker::sessions linkage */
- struct mg_connection *nc; /* Connection with the client */
- size_t num_subscriptions; /* Size of `subscriptions` array */
- struct mg_mqtt_topic_expression *subscriptions;
- void *user_data; /* User data */
-};
-MQTT session (Broker side).
-struct mg_mqtt_broker
-struct mg_mqtt_broker {
- struct mg_mqtt_session *sessions; /* Session list */
- void *user_data; /* User data */
-};
-MQTT broker.
-mg_mqtt_broker_init()
-void mg_mqtt_broker_init(struct mg_mqtt_broker *brk, void *user_data);
-Initialize a MQTT broker.
-mg_mqtt_broker()
-void mg_mqtt_broker(struct mg_connection *brk, int ev, void *data);
-Process a MQTT broker message.
-Listening connection expects a pointer to an initialized mg_mqtt_broker
-structure in the user_data field.
Basic usage:
-mg_mqtt_broker_init(&brk, NULL);
-
-if ((nc = mg_bind(&mgr, address, mg_mqtt_broker)) == NULL) {
- // fail;
-}
-nc->user_data = &brk;
-New incoming connections will receive a mg_mqtt_session structure
-in the connection user_data. The original user_data will be stored
-in the user_data field of the session structure. This allows the user
-handler to store user data before mg_mqtt_broker creates the session.
Since only the MG_EV_ACCEPT message is processed by the listening socket,
-for most events the user_data will thus point to a mg_mqtt_session.
mg_mqtt_next()
-struct mg_mqtt_session *mg_mqtt_next(struct mg_mqtt_broker *brk,
- struct mg_mqtt_session *s);
-Iterate over all mqtt sessions connections. Example:
-struct mg_mqtt_session *s;
-for (s = mg_mqtt_next(brk, NULL); s != NULL; s = mg_mqtt_next(brk, s)) {
- // Do something
-}
-CoAP
-CoAP message format:
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
-|Ver| T | TKL | Code | Message ID | Token (if any, TKL bytes) ...
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
-| Options (if any) ... |1 1 1 1 1 1 1 1| Payload (if any) ...
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
-struct mg_coap_option
-struct mg_coap_option {
- struct mg_coap_option *next;
- uint32_t number;
- struct mg_str value;
-};
-CoAP options. -Use mg_coap_add_option and mg_coap_free_options -for creation and destruction.
-struct mg_coap_message
-struct mg_coap_message {
- uint32_t flags;
- uint8_t msg_type;
- uint8_t code_class;
- uint8_t code_detail;
- uint16_t msg_id;
- struct mg_str token;
- struct mg_coap_option *options;
- struct mg_str payload;
- struct mg_coap_option *optiomg_tail;
-};
-CoAP message. See RFC 7252 for details.
-mg_set_protocol_coap()
-int mg_set_protocol_coap(struct mg_connection *nc);
-Set CoAP protocol handler - trigger CoAP specific events
-mg_coap_add_option()
-struct mg_coap_option *mg_coap_add_option(struct mg_coap_message *cm,
- uint32_t number, char *value,
- size_t len);
-Add new option to mg_coap_message structure. -Returns pointer to the newly created option.
-mg_coap_free_options()
-void mg_coap_free_options(struct mg_coap_message *cm);
-Free the memory allocated for options, -if cm paramater doesn’t contain any option does nothing.
-mg_coap_send_message()
-uint32_t mg_coap_send_message(struct mg_connection *nc,
- struct mg_coap_message *cm);
-Compose CoAP message from mg_coap_message
-and send it into nc connection.
-Return 0 on success. On error, it is a bitmask:
-
-
-
-
-#define MG_COAP_ERROR 0x10000
- -
-
-#define MG_COAP_FORMAT_ERROR (MG_COAP_ERROR | 0x20000)
- -
-
-#define MG_COAP_IGNORE (MG_COAP_ERROR | 0x40000)
- -
-
-#define MG_COAP_NOT_ENOUGH_DATA (MG_COAP_ERROR | 0x80000)
- -
-
-#define MG_COAP_NETWORK_ERROR (MG_COAP_ERROR | 0x100000)
-
mg_coap_send_ack()
-uint32_t mg_coap_send_ack(struct mg_connection *nc, uint16_t msg_id);
-Compose CoAP acknowledgement from mg_coap_message
-and send it into nc connection.
-Return value: see mg_coap_send_message()
mg_coap_parse()
-uint32_t mg_coap_parse(struct mbuf *io, struct mg_coap_message *cm);
-Parse COAP message and fills mg_coap_message and returns cm→flags. -This is a helper function.
-|
- |
--usually CoAP work over UDP, so lack of data means format error, -but in theory it is possible to use CoAP over TCP (according to RFC) - | -
The caller have to check results and treat COAP_NOT_ENOUGH_DATA according to -underlying protocol:
--
-
-
-
in case of UDP COAP_NOT_ENOUGH_DATA means COAP_FORMAT_ERROR,
-
- -
-
in case of TCP client can try to receive more data
-
-
Return value: see mg_coap_send_message()
mg_coap_compose()
-uint32_t mg_coap_compose(struct mg_coap_message *cm, struct mbuf *io);
-Composes CoAP message from mg_coap_message structure.
-This is a helper function.
-Return value: see mg_coap_send_message()
Utilities
-mg_skip()
-const char *mg_skip(const char *s, const char *end_string,
- const char *delimiters, struct mg_str *v);
-Fetch substring from input string s, end into v.
-Skips initial delimiter characters. Records first non-delimiter character
-as the beginning of substring v. Then scans the rest of the string
-until a delimiter character or end-of-string is found.
-delimiters is a 0-terminated string containing delimiter characters.
-Either one of delimiters or end_string terminates the search.
-Return an s pointer, advanced forward where parsing stopped.
mg_ncasecmp()
-int mg_ncasecmp(const char *s1, const char *s2, size_t len);
-Cross-platform version of strncasecmp().
mg_casecmp()
-int mg_casecmp(const char *s1, const char *s2);
-Cross-platform version of strcasecmp().
mg_vcmp()
-int mg_vcmp(const struct mg_str *str2, const char *str1);
-Cross-platform version of strcmp() where where first string is
-specified by struct mg_str.
mg_vcasecmp()
-int mg_vcasecmp(const struct mg_str *str2, const char *str1);
-Cross-platform version of strncasecmp() where first string is
-specified by struct mg_str.
mg_base64_decode()
-int mg_base64_decode(const unsigned char *s, int len, char *dst);
-Decode base64-encoded string s, len into the destination dst.
-Destination has to have enough space to hold decoded buffer.
-Decoding stops either when all string has been decoded, or invalid
-character appeared.
-Destination is '\0'-terminated.
-Return number of decoded characters. On success, that should be equal to
-len. On error (invalid character) the return value is smaller then len.
mg_base64_encode()
-void mg_base64_encode(const unsigned char *src, int src_len, char *dst);
-Base64-encode chunk of memory src, src_len into the destination dst.
-Destination has to have enough space to hold encoded buffer.
-Destination is '\0'-terminated.
mg_stat()
-int mg_stat(const char *path, cs_stat_t *st);
-Perform a 64-bit stat() call against given file.
path should be UTF8 encoded.
Return value is the same as for stat() syscall.
mg_fopen()
-FILE *mg_fopen(const char *path, const char *mode);
-Open the given file and return a file stream.
-path and mode should be UTF8 encoded.
Return value is the same as for the fopen() call.
mg_open()
-int mg_open(const char *path, int flag, int mode);
-Open the given file and return a file stream.
-path should be UTF8 encoded.
Return value is the same as for the open() syscall.
mg_start_thread()
-void *mg_start_thread(void *(*thread_func);
-Start a new detached thread.
-Arguments and semantic is the same as pthead’s pthread_create().
-thread_func is a thread function, thread_func_param is a parameter
-that is passed to the thread function.
mg_conn_addr_to_str()
-void mg_conn_addr_to_str(struct mg_connection *nc, char *buf, size_t len,
- int flags);
-Convert connection’s local or remote address into string.
-The flags parameter is a bit mask that controls the behavior,
-see MG_SOCK_STRINGIFY_* definitions.
-
-
-
-
MG_SOCK_STRINGIFY_IP - print IP address
-
- -
-
MG_SOCK_STRINGIFY_PORT - print port number
-
- -
-
MG_SOCK_STRINGIFY_REMOTE - print remote peer’s IP/port, not local address
-
-
If both port number and IP address are printed, they are separated by :.
-If compiled with -DMG_ENABLE_IPV6, IPv6 addresses are supported.
mg_sock_to_str()
-void mg_sock_to_str(sock_t sock, char *buf, size_t len, int flags);
-Legacy interface.
-mg_sock_addr_to_str()
-void mg_sock_addr_to_str(const union socket_address *sa, char *buf, size_t len,
- int flags);
-Convert socket’s address into string.
-flags is MG_SOCK_STRINGIFY_IP and/or MG_SOCK_STRINGIFY_PORT.
mg_hexdump()
-int mg_hexdump(const void *buf, int len, char *dst, int dst_len);
-Generates human-readable hexdump of memory chunk.
-Takes a memory buffer buf of length len and creates a hex dump of that
-buffer in dst. Generated output is a-la hexdump(1).
-Return length of generated string, excluding terminating \0. If returned
-length is bigger than dst_len, overflow bytes are discarded.
mg_hexdump_connection()
-void mg_hexdump_connection(struct mg_connection *nc, const char *path,
- const void *buf, int num_bytes, int ev);
-Generates human-readable hexdump of the data sent or received by connection.
-path is a file name where hexdump should be written. num_bytes is
-a number of bytes sent/received. ev is one of the MG_* events sent to
-an event handler. This function is supposed to be called from the
-event handler.
mg_avprintf()
-int mg_avprintf(char **buf, size_t size, const char *fmt, va_list ap);
-Print message to buffer. If buffer is large enough to hold the message, -return buffer. If buffer is to small, allocate large enough buffer on heap, -and return allocated buffer. -This is a supposed use case:
-char buf[5], *p = buf;
-p = mg_avprintf(&p, sizeof(buf), "%s", "hi there");
-use_p_somehow(p);
-if (p != buf) {
- free(p);
-}
-The purpose of this is to avoid malloc-ing if generated strings are small.
-mg_is_big_endian()
-int mg_is_big_endian(void);
-Return true if target platform is big endian.
-mg_next_comma_list_entry()
-const char *mg_next_comma_list_entry(const char *list, struct mg_str *val,
- struct mg_str *eq_val);
-A helper function for traversing a comma separated list of values.
-It returns a list pointer shifted to the next value, or NULL if the end
-of the list found.
-Value is stored in val vector. If value has form "x=y", then eq_val
-vector is initialized to point to the "y" part, and val vector length
-is adjusted to point only to "x".
-If list is just a comma separated list of entries, like "aa,bb,cc" then
-eq_val will contain zero-length string.
The purpose of this function is to parse comma separated string without -any copying/memory allocation.
-mg_match_prefix()
-int mg_match_prefix(const char *pattern, int pattern_len, const char *str);
-Match 0-terminated string (mg_match_prefix) or string with given length -mg_match_prefix_n against a glob pattern. -Match is case-insensitive. Return number of bytes matched, or -1 if no match.
-mg_mk_str()
-struct mg_str mg_mk_str(const char *s);
-A helper function for creating mg_str struct from plain C string.
-NULL is allowed and becomes {NULL, 0}.
MG_MK_STR()
-#define MG_MK_STR(str_literal);
-Macro for initializing mg_str.
-