mongoose/docs/README.md

4248 lines
110 KiB
Markdown
Raw Normal View History

2020-12-09 00:26:17 +08:00
# User Guide
2020-12-07 05:12:05 +08:00
2020-12-09 00:53:35 +08:00
2020-12-07 05:12:05 +08:00
## Introduction
Mongoose is a networking library for C/C++. It implements event-driven,
non-blocking APIs for TCP, UDP, HTTP, WebSocket, MQTT. It connects devices
2021-11-16 20:30:40 +08:00
and brings them online. Since 2004, a number of open source and commercial
products have utilized it. It even runs on the
2021-03-11 21:01:45 +08:00
International Space Station! Mongoose makes embedded network programming fast,
2020-12-07 05:12:05 +08:00
robust, and easy.
2021-08-28 15:52:41 +08:00
Mongoose has two basic data structures:
2020-12-07 05:12:05 +08:00
- `struct mg_mgr` - An event manager that holds all active connections
- `struct mg_connection` - A single connection descriptor
2020-12-07 05:12:05 +08:00
Connections could be listening, outbound, or inbound. Outbound
2020-12-07 05:12:05 +08:00
connections are created by the `mg_connect()` call. Listening connections are
created by the `mg_listen()` call. Inbound connections are those accepted by a
listening connection. Each connection is described by a `struct mg_connection`
structure, which has a number of fields. All fields are exposed to the
application by design, to give an application full visibility into
2020-12-07 05:12:05 +08:00
Mongoose's internals.
2021-11-16 20:30:40 +08:00
## 2-minute integration guide
2020-12-07 05:12:05 +08:00
2021-11-16 20:30:40 +08:00
In order to integrate Mongoose into an existing C/C++ application or firmware,
please use the following steps:
2020-12-07 05:12:05 +08:00
2021-09-17 22:59:15 +08:00
**Step 1.** Copy
[mongoose.c](https://raw.githubusercontent.com/cesanta/mongoose/master/mongoose.c)
and
[mongoose.h](https://raw.githubusercontent.com/cesanta/mongoose/master/mongoose.h)
into the source code tree
2020-12-07 05:12:05 +08:00
2021-09-17 22:59:15 +08:00
**Step 2.** Add the following lines in your `main.c` file:
2020-12-07 05:12:05 +08:00
2021-09-15 14:43:24 +08:00
```c
2021-09-17 22:59:15 +08:00
#include "mongoose.h"
...
2021-09-15 14:43:24 +08:00
static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
2021-09-17 22:59:15 +08:00
struct mg_http_serve_opts opts = {.root_dir = "."}; // Serve local dir
if (ev == MG_EV_HTTP_MSG) mg_http_serve_dir(c, ev_data, &opts);
2021-09-15 14:43:24 +08:00
}
2021-09-17 22:59:15 +08:00
...
int main() {
...
2021-09-15 14:43:24 +08:00
2021-09-17 22:59:15 +08:00
struct mg_mgr mgr;
mg_mgr_init(&mgr);
mg_http_listen(&mgr, "0.0.0.0:8000", fn, NULL); // Create listening connection
for (;;) mg_mgr_poll(&mgr, 1000); // Block forever
}
2021-09-15 14:43:24 +08:00
```
2020-12-07 05:12:05 +08:00
**Step 3.** Add `mongoose.c` to the build and recompile - and that is it!
2020-12-07 05:12:05 +08:00
2021-09-15 14:43:24 +08:00
`mg_mgr_poll()` iterates over all connections, accepts new connections, sends and
receives data, closes connections, and calls event handler functions for the
2021-09-15 14:43:24 +08:00
respective events.
2020-12-07 05:12:05 +08:00
2021-09-22 18:51:16 +08:00
Each connection has two event handler functions: `c->fn` and `c->pfn`. The
`c->fn` is a user-specified event handler function. The `c->pfn` is a
protocol-specific handler function that is set implicitly. For example, a
`mg_http_listen()` sets `c->pfn` to a Mongoose's HTTP event handler. A
protocol-specific handler is called before a user-specific handler. It parses
2021-09-22 18:51:16 +08:00
incoming data and may invoke protocol-specific events like `MG_EV_HTTP_MSG`.
2021-09-17 22:59:15 +08:00
<span class="badge bg-danger">NOTE:</span>
Since Mongoose's core is not protected against concurrent accesses, make
2021-09-17 22:59:15 +08:00
sure that all `mg_*` API functions are called from the same thread or RTOS
task.
2020-12-07 05:12:05 +08:00
## Send and receive buffers
Each connection has a send and receive buffer:
- `struct mg_connection::send` - Data to be sent to a peer
- `struct mg_connection::recv` - Data received from a peer
2020-12-07 05:12:05 +08:00
When data arrives, Mongoose appends received data to the `recv` and triggers a
2021-05-19 07:19:21 +08:00
`MG_EV_READ` event. The user may send data back by calling one of the output
functions, like `mg_send()`, `mg_printf()` or a protocol-specific function like
2021-09-15 14:43:24 +08:00
`mg_ws_send`. Output functions append data to the `send` buffer. When Mongoose
successfully writes data to the socket, it discards data from struct `mg_connection::send`
and sends an `MG_EV_WRITE` event.
2020-12-07 05:12:05 +08:00
## Event handler function
Each connection has an event handler function associated with it, which
must be implemented by the user. Event handler is the key element of
Mongoose, since it defines the connection's behavior. See below
2021-11-16 20:30:40 +08:00
for an example of an event handler function:
2020-12-07 05:12:05 +08:00
```c
2021-08-21 03:31:32 +08:00
// Event handler function defines connection's behavior
2020-12-07 05:12:05 +08:00
static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
2021-08-21 03:31:32 +08:00
if (ev == MG_EV_READ) {
mg_send(c, c->recv.buf, c->recv.len); // Implement echo server
c->recv.len = 0; // Delete received data
2020-12-07 05:12:05 +08:00
}
}
```
- `struct mg_connection *c` - A connection that received an event
- `int ev` - An event number, defined in mongoose.h. For example, when data
2021-11-16 20:30:40 +08:00
arrives on an inbound connection, `ev` would be `MG_EV_READ`
- `void *ev_data` - Points to the event-specific data, and it has a different
2021-05-19 07:19:21 +08:00
meaning for different events. For example, for an `MG_EV_READ` event,
2020-12-07 05:12:05 +08:00
`ev_data`
is an `int *` pointing to the number of bytes received from a remote
peer and saved into the `c->recv` IO buffer. The exact meaning of `ev_data` is
described for each event. Protocol-specific events usually have `ev_data`
2020-12-10 21:26:05 +08:00
pointing to structures that hold protocol-specific information
- `void *fn_data` - A user-defined pointer for the connection, which is a
2021-08-28 18:16:45 +08:00
placeholder for application-specific data. This `fn_data` pointer is set
during the `*_listen()` or `*_connect()` call, and it is stored in the
`c->fn_data`. Listening connections copy the value of `c->fn_data` to the
newly accepted connection, so all accepted connections initially share the
same `fn_data` pointer. It is fine to update/replace that pointer for
any connection at any time by setting `c->fn_data = new_value;`
2020-12-07 05:12:05 +08:00
## Events
2021-03-11 21:01:45 +08:00
Below is the list of events triggered by Mongoose, taken as-is from `mongoose.h`.
For each event, a comment describes the meaning of the `ev_data` pointer passed
2020-12-07 05:12:05 +08:00
to an event handler:
```c
enum {
2021-12-22 06:20:42 +08:00
MG_EV_ERROR, // Error char *error_message
MG_EV_OPEN, // Connection created NULL
MG_EV_POLL, // mg_mgr_poll iteration uint64_t *milliseconds
2021-12-22 06:20:42 +08:00
MG_EV_RESOLVE, // Host name is resolved NULL
MG_EV_CONNECT, // Connection established NULL
MG_EV_ACCEPT, // Connection accepted NULL
MG_EV_READ, // Data received from socket struct mg_str *
MG_EV_WRITE, // Data written to socket long *bytes_written
MG_EV_CLOSE, // Connection closed NULL
MG_EV_HTTP_MSG, // HTTP request/response struct mg_http_message *
MG_EV_HTTP_CHUNK, // HTTP chunk (partial msg) struct mg_http_message *
MG_EV_WS_OPEN, // Websocket handshake done struct mg_http_message *
MG_EV_WS_MSG, // Websocket msg, text or bin struct mg_ws_message *
MG_EV_WS_CTL, // Websocket control msg struct mg_ws_message *
MG_EV_MQTT_CMD, // MQTT low-level command struct mg_mqtt_message *
MG_EV_MQTT_MSG, // MQTT PUBLISH received struct mg_mqtt_message *
MG_EV_MQTT_OPEN, // MQTT CONNACK received int *connack_status_code
MG_EV_SNTP_TIME, // SNTP time received uint64_t *milliseconds
2021-12-22 06:20:42 +08:00
MG_EV_USER, // Starting ID for user events
2020-12-07 05:12:05 +08:00
};
```
## Connection flags
`struct mg_connection` has a bitfield with connection flags. Flags are binary:
2020-12-07 05:12:05 +08:00
they can be either 0 or 1. Some flags are set by Mongoose and must be not
changed by an application code. For example, the `is_udp` flag tells the application if
2020-12-07 05:12:05 +08:00
that connection is UDP or not. Some flags can be changed by application, for
example, the `is_draining` flag, if set by an application, tells Mongoose to send
the remaining data to a peer, and when everything is sent, close the connection.
2020-12-07 05:12:05 +08:00
2021-12-19 18:53:17 +08:00
<span class="badge bg-danger me-1"> NOTE: </span>User-changeable flags are:
`is_hexdumping`, `is_draining`, `is_closing`.
2020-12-07 05:12:05 +08:00
This is taken from `mongoose.h` as-is:
```c
struct mg_connection {
...
unsigned is_listening : 1; // Listening connection
unsigned is_client : 1; // Outbound (client) connection
unsigned is_accepted : 1; // Accepted (server) connection
unsigned is_resolving : 1; // Non-blocking DNS resolv is in progress
unsigned is_connecting : 1; // Non-blocking connect is in progress
unsigned is_tls : 1; // TLS-enabled connection
unsigned is_tls_hs : 1; // TLS handshake is in progress
unsigned is_udp : 1; // UDP connection
unsigned is_websocket : 1; // WebSocket connection
unsigned is_hexdumping : 1; // Hexdump in/out traffic
unsigned is_draining : 1; // Send remaining data, then close and free
unsigned is_closing : 1; // Close and free the connection immediately
unsigned is_full : 1; // Stop reads, until cleared
2022-08-06 02:27:56 +08:00
unsigned is_resp : 1; // Response is still being generated
2020-12-07 05:12:05 +08:00
unsigned is_readable : 1; // Connection is ready to read
unsigned is_writable : 1; // Connection is ready to write
};
```
2022-04-24 18:26:25 +08:00
## Best practices
- If you need to perform any sort of initialisation of your connection,
do it by catching `MG_EV_OPEN` event. That event is sent immediately
after a connection has been allocated and added to the event manager,
but before anything else:
```c
2022-04-24 18:33:47 +08:00
static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
2022-04-24 18:26:25 +08:00
if (ev == MG_EV_OPEN) {
... // Do your initialisation
}
```
- If you need to keep some connection-specific data, you have two options.
First, use `c->fn_data` pointer. That pointer is passed to the event handler
2022-04-24 18:33:47 +08:00
as last parameter:
```c
static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
if (ev == MG_EV_OPEN) {
c->fn_data = malloc(123); // Change our fn_data
} else if (ev == MG_EV_CLOSE) {
free(fn_data); // Don't forget to free!
}
...
}
2022-04-24 18:37:23 +08:00
// Every accepted connection inherit NULL pointer as c->fn_data, but we change
2022-04-24 18:33:47 +08:00
// it per-connection to something else
2022-04-24 18:37:23 +08:00
mg_http_listen(&mgr, "http://localhost:1234", fn, NULL);
2022-04-24 18:33:47 +08:00
```
Another option is to use `c->label` buffer, which can
hold some amount of connection-specific data without extra memory allocation:
```c
static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
if (ev == MG_EV_WS_OPEN) {
c->label[0] = 'W'; // Established websocket connection, store something
...
```
2022-04-24 18:39:54 +08:00
- If you need to close the connection, set `c->is_draining = 1;` in your
2022-04-24 18:26:25 +08:00
event handler function. That tells the event manager to send all remaining
2022-04-24 18:39:54 +08:00
data in a send buffer ("drain" the connection), then close the connection.
If you need to close
the connection immediately without draining, use `c->is_closing = 1;`
2022-04-24 18:26:25 +08:00
- Use `mg_http_reply()` function to create HTTP responses. That function
properly sets the `Content-Length` header, which is important. Of course
you can create responses manually, e.g. with `mg_printf()` function,
but be sure to set the `Content-Length` header:
```c
mg_printf(c, "HTTP/1.1 200 OK\r\Content-Length: %d\r\n\r\n%s", 2, "hi");
```
Alternatively, use chunked transfer enconding:
```c
mg_printf(c, "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n");
mg_http_printf_chunk(c, "%s", "foo");
mg_http_printf_chunk(c, "%s", "bar");
mg_http_printf_chunk(c, ""); // Don't forget the last empty chunk
```
2022-08-06 02:27:56 +08:00
<span class="badge bg-danger">NOTE:</span> if you are not using
`mg_http_reply()` or `mg_http_*_chunk()`, make sure to set
`c->is_resp = 0;` when your event handler finished writing response.
2022-05-12 22:07:02 +08:00
- On embedded environment, make sure that serving task has enough stack:
give it 2k for simple RESTful serving, or 4-8k for complex dynamic/static
serving. In certain environments, it is necessary to adjust heap size, too.
By default, IO buffer allocation size `MG_IO_SIZE` is 2048: change it to 512
to trim run-time per-connection memory consumption.
2022-04-24 18:26:25 +08:00
2020-12-07 05:12:05 +08:00
## Build options
Mongoose source code ships in two files:
- [mongoose.h](https://github.com/cesanta/mongoose/blob/master/mongoose.h) - API definitions
- [mongoose.c](https://github.com/cesanta/mongoose/blob/master/mongoose.c) - Implementation
2020-12-07 05:12:05 +08:00
Therefore, to integrate Mongoose into an application, simply copy these two
files to the application's source tree. The `mongoose.c` and `mongoose.h` files
are actually an amalgamation - non-amalgamated sources can be found at
https://github.com/cesanta/mongoose/tree/master/src
2020-12-07 05:12:05 +08:00
Mongoose has two types of build constants (preprocessor definitions) that
affect the build: a target architecture, and tunables. In order to set the
option during build time, use the `-D OPTION` compiler flag:
2020-12-07 05:12:05 +08:00
```sh
$ cc app0.c mongoose.c # Use defaults!
$ cc app1.c mongoose.c -D MG_ENABLE_IPV6=1 # Build with IPv6 enabled
2021-05-29 06:49:26 +08:00
$ cc app2.c mongoose.c -D MG_ARCH=MG_ARCH_FREERTOS_LWIP # Set architecture
$ cc app3.c mongoose.c -D MG_ENABLE_SSI=0 -D MG_IO_SIZE=8192 # Multiple options
2020-12-07 05:12:05 +08:00
```
2021-09-15 14:43:24 +08:00
The list of supported architectures is defined in the [arch.h](https://github.com/cesanta/mongoose/blob/master/src/arch.h)
header file. Normally, there is no need to explicitly specify the architecture.
The architecture is guessed during the build, so setting it is not usually required.
| Name | Description |
| ---- | ----------- |
|MG_ARCH_UNIX | All UNIX-like systems like Linux, MacOS, FreeBSD, etc |
|MG_ARCH_WIN32 | Windows systems |
|MG_ARCH_ESP32 | Espressif's ESP32 |
|MG_ARCH_ESP8266 | Espressif's ESP8266 |
2021-05-29 06:49:26 +08:00
|MG_ARCH_FREERTOS_LWIP | All systems with FreeRTOS kernel and LwIP IP stack |
|MG_ARCH_FREERTOS_TCP | All systems with FreeRTOS kernel and FreeRTOS-Plus-TCP IP stack |
|MG_ARCH_CUSTOM | A custom architecture, discussed in the next section |
The other class of build constants is defined in
[src/config.h](https://github.com/cesanta/mongoose/blob/master/src/config.h)
together with their default values. These are tunables that include/exclude
a certain functionality or change relevant parameters.
2020-12-07 05:12:05 +08:00
Here is a list of build constants and their default values:
2020-12-09 00:26:17 +08:00
2020-12-07 05:12:05 +08:00
| Name | Default | Description |
| ---- | ------- | ----------- |
|MG_ENABLE_SOCKET | 1 | Use BSD socket low-level API |
2021-11-16 20:30:40 +08:00
|MG_ENABLE_MBEDTLS | 0 | Enable mbedTLS library |
|MG_ENABLE_OPENSSL | 0 | Enable OpenSSL library |
|MG_ENABLE_IPV6 | 0 | Enable IPv6 |
|MG_ENABLE_MD5 | 0 | Use native MD5 implementation |
2021-07-29 21:21:20 +08:00
|MG_ENABLE_SSI | 1 | Enable serving SSI files by `mg_http_serve_dir()` |
2021-07-30 20:19:20 +08:00
|MG_ENABLE_CUSTOM_RANDOM | 0 | Provide custom RNG function `mg_random()` |
2022-04-05 01:14:59 +08:00
|MG_ENABLE_CUSTOM_TLS | 0 | Enable custom TLS library |
|MG_ENABLE_CUSTOM_MILLIS | 0 | Enable custom `mg_millis()` function |
2021-07-30 20:19:20 +08:00
|MG_ENABLE_PACKED_FS | 0 | Enable embedded FS support |
2022-01-18 15:44:30 +08:00
|MG_ENABLE_FATFS | 0 | Enable embedded FAT FS support |
|MG_ENABLE_LINES | undefined | If defined, show source file names in logs |
2021-07-29 21:21:20 +08:00
|MG_IO_SIZE | 2048 | Granularity of the send/recv IO buffer growth |
|MG_MAX_RECV_SIZE | (3 * 1024 * 1024) | Maximum recv buffer size |
|MG_MAX_HTTP_HEADERS | 40 | Maximum number of HTTP headers |
|MG_HTTP_INDEX | "index.html" | Index file for HTML directory |
2022-01-18 15:44:30 +08:00
|MG_FATFS_ROOT | "/" | FAT FS root directory |
2020-12-07 05:12:05 +08:00
2021-08-21 03:31:32 +08:00
<span class="badge bg-danger">NOTE:</span> the `MG_IO_SIZE` constant also sets
maximum UDP message size, see
[issues/907](https://github.com/cesanta/mongoose/issues/907) for details. If the
2021-08-21 03:31:32 +08:00
application uses large UDP messages, increase the `MG_IO_SIZE` limit
accordingly.
2020-12-17 19:19:13 +08:00
2021-01-20 19:28:47 +08:00
## Custom build
A custom build should be used for cases which is not covered by the
existing architecture options (e.g., an embedded architecture that
uses some proprietary RTOS and network stack). In order to build on such
systems, follow the outline below:
2021-05-12 18:39:46 +08:00
1. Add `-DMG_ARCH=MG_ARCH_CUSTOM` to your build flags.
2. Create a file called `mongoose_custom.h`, with defines and includes that
2021-01-20 19:28:47 +08:00
are relevant to your platform. Mongoose uses `bool` type, `MG_DIRSEP` define,
and optionally other structures like `DIR *` depending on the functionality
2021-05-29 06:49:26 +08:00
you have enabled - see previous section. Below is an example:
2021-05-12 18:39:46 +08:00
```c
2021-09-15 14:43:24 +08:00
#include <stdbool.h>
2021-05-12 18:39:46 +08:00
#include <stdarg.h>
2021-01-20 19:28:47 +08:00
#define MG_DIRSEP '/'
2021-05-12 18:39:46 +08:00
#define MG_INT64_FMT "%lld"
2021-01-20 19:28:47 +08:00
```
2022-05-26 09:10:28 +08:00
3. This step is optional, and only required if you intend to use a custom
TCP/IP stack. To do that, you should:
* Disable BSD socket API: in the `mongoose_custom.h`, add
```c
#define MG_ENABLE_SOCKET 0
```
* Add an implementation of several internal API functions, like
`mg_send()`, `mg_mgr_poll()`, etc. For the reference, take
a look at the stub
"do nothing" implementation at
[test/mongoose_custom.c](https://github.com/cesanta/mongoose/blob/master/test/mongoose_custom.c)
and the experimental builtin bare metal TCP/IP stack implementation
at
[src/mip.c](https://github.com/cesanta/mongoose/blob/master/src/mip.c)
2021-01-20 19:28:47 +08:00
2020-12-09 00:26:17 +08:00
## Minimal HTTP server
2020-12-07 05:12:05 +08:00
2022-05-12 15:07:51 +08:00
This example is a simple HTTP server that serves both static and dynamic content:
2020-12-07 05:12:05 +08:00
```c
#include "mongoose.h"
2021-08-22 17:51:40 +08:00
static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
2022-05-12 15:07:51 +08:00
if (ev == MG_EV_HTTP_MSG) {
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
if (mg_http_match_uri(hm, "/api/hello")) {
mg_http_reply(c, 200, "", "%s\n", "hi"); // Serve dynamic content
} else {
struct mg_http_serve_opts opts = {.root_dir = "."}; // Serve
mg_http_serve_dir(c, ev_data, &opts); // static content
}
}
2020-12-07 05:12:05 +08:00
}
int main(int argc, char *argv[]) {
struct mg_mgr mgr;
2022-05-12 15:07:51 +08:00
mg_mgr_init(&mgr); // Init manager
mg_http_listen(&mgr, "http://0.0.0.0:8000", fn, &mgr); // Setup listener
for (;;) mg_mgr_poll(&mgr, 1000); // Event loop
mg_mgr_free(&mgr); // Cleanup
2020-12-07 05:12:05 +08:00
return 0;
}
```
2020-12-09 00:26:17 +08:00
## Minimal TCP echo server
This example is a simple TCP echo server that listens on port 1234:
```c
#include "mongoose.h"
static void cb(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
2021-05-19 07:19:21 +08:00
if (ev == MG_EV_READ) {
2020-12-09 00:26:17 +08:00
mg_send(c, c->recv.buf, c->recv.len); // Echo received data back
2021-08-28 14:16:38 +08:00
mg_iobuf_del(&c->recv, 0, c->recv.len); // And discard it
2020-12-09 00:26:17 +08:00
}
}
int main(int argc, char *argv[]) {
struct mg_mgr mgr;
2021-09-15 14:43:24 +08:00
mg_mgr_init(&mgr); // Init manager
mg_listen(&mgr, "tcp://0.0.0.0:1234", cb, &mgr); // Setup listener
for (;;) mg_mgr_poll(&mgr, 1000); // Event loop
mg_mgr_free(&mgr); // Cleanup
2020-12-09 00:26:17 +08:00
return 0;
}
```
# API Reference
## Core
2021-09-15 14:43:24 +08:00
### struct mg\_addr
```c
struct mg_addr {
uint16_t port; // TCP or UDP port in network byte order
uint32_t ip; // IP address in network byte order
uint8_t ip6[16]; // IPv6 address
bool is_ip6; // True when address is IPv6 address
};
```
This structure contains network address; it can be considered as a Mongoose equivalent for sockets `sockaddr` structure.
2021-09-15 14:43:24 +08:00
### struct mg\_mgr
2020-12-09 00:26:17 +08:00
```c
2020-12-09 00:53:35 +08:00
struct mg_mgr {
2020-12-09 00:26:17 +08:00
struct mg_connection *conns; // List of active connections
2021-08-12 19:24:28 +08:00
struct mg_dns dns4; // DNS for IPv4
struct mg_dns dns6; // DNS for IPv6
2020-12-09 00:26:17 +08:00
int dnstimeout; // DNS resolve timeout in milliseconds
2021-08-12 19:24:28 +08:00
unsigned long nextid; // Next connection ID
void *userdata; // Arbitrary user data pointer
2020-12-09 00:26:17 +08:00
};
```
Event management structure that holds a list of active connections, together
with some housekeeping information.
### struct mg\_connection
```c
struct mg_connection {
struct mg_connection *next; // Linkage in struct mg_mgr :: connections
struct mg_mgr *mgr; // Our container
2022-02-23 06:00:55 +08:00
struct mg_addr loc; // Local address
struct mg_addr rem; // Remote address
2020-12-09 00:26:17 +08:00
void *fd; // Connected socket, or LWIP data
2021-05-19 07:19:21 +08:00
unsigned long id; // Auto-incrementing unique connection ID
2020-12-09 00:26:17 +08:00
struct mg_iobuf recv; // Incoming data
struct mg_iobuf send; // Outgoing data
mg_event_handler_t fn; // User-specified event handler function
2021-03-11 21:01:45 +08:00
void *fn_data; // User-specified function parameter
2020-12-09 00:26:17 +08:00
mg_event_handler_t pfn; // Protocol-specific handler function
void *pfn_data; // Protocol-specific function parameter
2021-05-19 07:19:21 +08:00
char label[50]; // Arbitrary label
2020-12-09 00:26:17 +08:00
void *tls; // TLS specific data
unsigned is_listening : 1; // Listening connection
unsigned is_client : 1; // Outbound (client) connection
unsigned is_accepted : 1; // Accepted (server) connection
2021-03-11 21:01:45 +08:00
unsigned is_resolving : 1; // Non-blocking DNS resolve is in progress
2020-12-09 00:26:17 +08:00
unsigned is_connecting : 1; // Non-blocking connect is in progress
unsigned is_tls : 1; // TLS-enabled connection
unsigned is_tls_hs : 1; // TLS handshake is in progress
unsigned is_udp : 1; // UDP connection
unsigned is_websocket : 1; // WebSocket connection
unsigned is_hexdumping : 1; // Hexdump in/out traffic
unsigned is_draining : 1; // Send remaining data, then close and free
unsigned is_closing : 1; // Close and free the connection immediately
unsigned is_full : 1; // Stop reads, until cleared
2022-08-06 02:27:56 +08:00
unsigned is_resp : 1; // Response is still being generated
2020-12-09 00:26:17 +08:00
unsigned is_readable : 1; // Connection is ready to read
unsigned is_writable : 1; // Connection is ready to write
};
```
A connection - either a listening connection, or an accepted connection,
2021-03-11 21:01:45 +08:00
or an outbound connection.
2020-12-09 00:26:17 +08:00
2021-09-15 14:43:24 +08:00
### mg\_mgr\_init()
2020-12-09 00:26:17 +08:00
```c
2021-08-12 19:24:28 +08:00
void mg_mgr_init(struct mg_mgr *mgr);
```
Initialize event manager structure:
- Set a list of active connections to NULL
- Set default DNS servers for IPv4 and IPv6
- Set default DNS lookup timeout
Parameters:
2021-09-15 20:37:57 +08:00
- `mgr` - a pointer to `mg_mgr` structure that needs to be initialized
2021-08-12 19:24:28 +08:00
Return value: none
Usage example:
```c
struct mg_mgr mgr;
mg_mgr_init(&mgr);
2020-12-09 00:26:17 +08:00
```
2021-09-15 14:43:24 +08:00
### mg\_mgr\_poll()
2020-12-09 00:26:17 +08:00
```c
void mg_mgr_poll(struct mg_mgr *mgr, int ms);
```
Perform a single poll iteration. For each connection in the `mgr->conns` list:
- See if there is incoming data. If there is, read it into the `c->recv` buffer, send `MG_EV_READ` event
2020-12-09 00:26:17 +08:00
- See if there is data in the `c->send` buffer, and write it, send `MG_EV_WRITE` event
- If a connection is listening, accept an incoming connection if any, and send `MG_EV_ACCEPT` event to it
- Send `MG_EV_POLL` event
2021-09-15 20:37:57 +08:00
Parameters:
2021-09-22 18:51:16 +08:00
- `mgr` - an event manager to use
- `ms` - a timeout in milliseconds
2021-09-15 20:37:57 +08:00
Return value: none
2021-09-15 14:43:24 +08:00
Usage example:
```c
while (running == true) mg_mgr_poll(&mgr, 1000 /* 1 sec */);
```
2020-12-09 00:26:17 +08:00
2021-01-23 15:49:55 +08:00
### mg\_mgr\_free()
2020-12-09 00:26:17 +08:00
```c
void mg_mgr_free(struct mg_mgr *mgr);
```
Close all connections, and free all resources.
2021-09-15 20:37:57 +08:00
Parameters:
2021-09-22 18:51:16 +08:00
- `mgr` - an event manager to cleanup
2021-09-15 20:37:57 +08:00
Return value: none
2021-09-15 14:43:24 +08:00
Usage example:
```c
struct mg_mgr mgr;
mg_mgr_init(&mgr);
while (running == true) mg_mgr_poll(&mgr, 1000); // Event loop
mg_mgr_free(&mgr);
```
2020-12-09 00:26:17 +08:00
### mg\_listen()
```c
struct mg_connection *mg_listen(struct mg_mgr *mgr, const char *url,
mg_event_handler_t fn, void *fn_data);
```
Create a listening connection, append this connection to `mgr->conns`.
2021-09-15 20:37:57 +08:00
Parameters:
2021-09-22 18:51:16 +08:00
- `mgr` - an event manager to use
- `url` - a URL. Specifies local IP address and port to listen on, e.g.
2020-12-09 00:26:17 +08:00
`tcp://127.0.0.1:1234` or `udp://0.0.0.0:9000`
- `fn` - an event handler function
- `fn_data` - an arbitrary pointer, which will be passed as `fn_data` when an
event handler is called. This pointer is also stored in a connection
structure as `c->fn_data`
Return value: created connection, or `NULL` on error.
2021-09-15 14:43:24 +08:00
Usage example:
```c
struct mg_connection *c = mg_listen(&mgr, "tcp://127.0.0.1:8080", fn, NULL);
```
2020-12-09 00:26:17 +08:00
### mg\_connect()
```c
struct mg_connection *mg_connect(struct mg_mgr *mgr, const char *url,
mg_event_handler_t fn, void *fn_data);
```
2021-03-11 21:01:45 +08:00
Create an outbound connection, append this connection to `mgr->conns`.
2021-09-15 20:37:57 +08:00
Parameters:
- `mgr` - An event manager to use
- `url` - A URL, specifies remote IP address/port to connect to, e.g. `http://a.com`
- `fn` - An event handler function
- `fn_data` - An arbitrary pointer, which will be passed as `fn_data` when an
2020-12-09 00:26:17 +08:00
event handler is called. This pointer is also stored in a connection
structure as `c->fn_data`
Return value: created connection, or `NULL` on error.
Note: This function does not connect to peer, it allocates required resources and
starts connect process. Once peer is really connected, `MG_EV_CONNECT` event is sent
2021-09-15 14:43:24 +08:00
to connection event handler.
Usage example:
```c
struct mg_connection *c = mg_connect(&mgr, "http://example.org", fn, NULL);
```
2020-12-09 00:26:17 +08:00
### mg\_send()
```c
int mg_send(struct mg_connection *c, const void *data, size_t size);
```
Append `data` of size `size` to the `c->send` buffer. Return number of bytes
appended.
Note: This function does not push data to the network. It only appends data to
2020-12-09 00:26:17 +08:00
the output buffer. The data is being sent when `mg_mgr_poll()` is called. If
`mg_send()` is called multiple times, the output buffer grows.
2021-09-15 20:37:57 +08:00
Parameters:
- `c` - A connection pointer
- `data` - A pointer to data to append to the send buffer
- `size` - A data size
2021-09-15 20:37:57 +08:00
Return value: `true` if data appended successfully and `false` otherwise
2021-09-15 14:43:24 +08:00
Usage example:
```c
mg_send(c, "hi", 2); // Append string "hi" to the output buffer
```
2020-12-09 00:26:17 +08:00
2022-02-11 01:11:03 +08:00
### mg\_printf(), mg\_vprintf()
2020-12-09 00:26:17 +08:00
```c
int mg_printf(struct mg_connection *, const char *fmt, ...);
2022-02-11 01:11:03 +08:00
int mg_vprintf(struct mg_connection *, const char *fmt, va_list ap);
2020-12-09 00:26:17 +08:00
```
Same as `mg_send()`, but formats data using `printf()` semantics. Return
number of bytes appended to the output buffer.
2022-02-11 01:11:03 +08:00
<span class="badge bg-danger">NOTE: </span> See [mg\_snprintf](#mg_snprintf-mg_vsnprintf)
for the list of supported format specifiers
2020-12-09 00:26:17 +08:00
2021-09-15 20:37:57 +08:00
Parameters:
2021-09-22 18:51:16 +08:00
- `c` - a connection pointer
- `fmt` - a format string in `printf` semantics
2021-09-15 20:37:57 +08:00
Return value: number of bytes appended to the output buffer.
2021-09-15 14:43:24 +08:00
Usage example:
```c
mg_printf(c, "Hello, %s!", "world"); // Add "Hello, world!" to output buffer
```
2020-12-09 00:26:17 +08:00
2021-09-15 14:43:24 +08:00
### mg\_straddr
```c
2022-01-06 03:09:11 +08:00
char *mg_straddr(struct mg_addr *addr, char *buf, size_t len);
2021-09-15 14:43:24 +08:00
```
Write stringified IP address, associated with given connection to `buf` (maximum size `len`)
2021-09-15 20:37:57 +08:00
Parameters:
2022-01-06 03:09:11 +08:00
- `addr` - A address pointer
- `buf` - A pointer to a buffer that will hold stringified address
- `len` - A buffer size
2021-09-15 20:37:57 +08:00
Return value: `buf` value
2021-09-15 14:43:24 +08:00
Usage example:
```c
2022-01-06 03:09:11 +08:00
char buf[100];
LOG(LL_INFO, ("%s", mg_straddr(&c->peer, buf, sizeof(buf))));
2021-09-15 14:43:24 +08:00
```
2020-12-09 00:26:17 +08:00
2022-04-22 21:42:07 +08:00
### mg\_wrapfd()
2020-12-09 00:26:17 +08:00
```c
2022-04-22 21:42:07 +08:00
struct mg_connection *mg_wrapfd(struct mg_mgr *mgr, int fd,
mg_event_handler_t fn, void *fn_data);
2020-12-09 00:26:17 +08:00
```
2022-04-22 21:42:07 +08:00
Wrap a given file descriptor `fd` into a connection, and add that connection
to the event manager. An `fd` descriptor must suport `send()`, `recv()`,
`select()` syscalls, and be non-blocking. Mongoose will treat it as a TCP
socket. The `c->rem` and `c->loc` addresses will be empty.
2021-08-09 16:43:21 +08:00
2021-09-15 20:37:57 +08:00
Parameters:
2022-04-22 21:42:07 +08:00
- `fd` - A file descriptor to wrap
- `mgr` - An event manager
- `fn` - A pointer to event handler function
- `ud` - A user data pointer. It will be passed to `fn` as `fn_data` parameter
2021-09-15 20:37:57 +08:00
2022-04-22 21:42:07 +08:00
Return value: Pointer to the created connection or `NULL` in case of error
### mg\_mkpipe()
```c
int mg_mkpipe(struct mg_mgr *mgr, mg_event_handler_t fn, void *fn_data, bool udp);
2022-04-22 21:42:07 +08:00
```
Create two interconnected sockets for inter-thread communication. One socket
is wrapped into a Mongoose connection and is added to the event manager.
Another socket is returned, and supposed to be passed to a worker thread.
When a worker thread `send()`s to socket any data, that wakes up `mgr` and
`fn` event handler reveives `MG_EV_READ` event. Also, `fn` can send any
data to a worker thread, which can be `recv()`ed by a worker thread.
If a socketpair is UDP, then it is guaranteed to send a
2022-04-22 21:42:07 +08:00
Parameters:
- `mgr` - an event manager
- `fn` - a pointer to event handler function
- `fn_data` - a user data pointer. It will be passed to `fn` as `fn_data` parameter
- `udp` - tells to create UDP or TCP socketpair.
2022-04-22 21:42:07 +08:00
Return value: created socket, or `-1` on error
2021-09-15 20:37:57 +08:00
2021-11-16 20:30:40 +08:00
Usage example: see [examples/multi-threaded](https://github.com/cesanta/mongoose/tree/master/examples/multi-threaded).
2021-09-15 14:43:24 +08:00
### mg\_mgr\_wakeup()
2021-08-12 19:24:28 +08:00
```c
bool mg_mgr_wakeup(struct mg_connection *pipe, const void *buf, size_len len);
2021-08-12 19:24:28 +08:00
```
Wake up an event manager that sleeps in `mg_mgr_poll()` call. This function
2022-01-19 17:25:01 +08:00
must be called from a separate task/thread. A calling thread can pass
2022-02-19 23:31:22 +08:00
some specific data to the IO thread via `buf`, `len`. The maximum value
of `len` is limited by a maximum UDP datagram size, which is 64KiB. If you need
2022-02-19 21:46:07 +08:00
to send a large data to the Mongoose thread, `malloc()` the data and send
a pointer to it, not the data itself. The receiving event handler can receive
a pointer, send a response, and call `free()`. Parameters:
2021-08-12 19:24:28 +08:00
2021-09-15 20:37:57 +08:00
Parameters:
2021-08-12 19:24:28 +08:00
- `pipe` - a special connection created by the `mg_mkpipe()` call
2022-01-19 17:25:01 +08:00
- `buf` - a data to send to the pipe connection. Use `""` if there is no data
- `len` - a data length
2021-08-12 19:24:28 +08:00
Return value: `true` if data has been sent, `false` otherwise
2021-09-15 20:37:57 +08:00
2021-11-16 20:30:40 +08:00
Usage example: see [examples/multi-threaded](https://github.com/cesanta/mongoose/tree/master/examples/multi-threaded).
2021-08-12 19:24:28 +08:00
2020-12-09 00:26:17 +08:00
## HTTP
### struct mg\_http\_header
```c
struct mg_http_header {
2021-09-15 14:43:24 +08:00
struct mg_str name; // Header name
struct mg_str value; // Header value
2020-12-09 00:26:17 +08:00
};
```
2021-09-15 14:43:24 +08:00
Structure represents HTTP header, like `Content-Type: text/html`.
`Content-Type` is a header name and `text/html` is a header value.
2020-12-09 00:26:17 +08:00
### struct mg\_http\_message
```c
struct mg_http_message {
2021-09-15 14:43:24 +08:00
struct mg_str method, uri, query, proto; // Request/response line
2020-12-09 00:26:17 +08:00
struct mg_http_header headers[MG_MAX_HTTP_HEADERS]; // Headers
2021-09-15 14:43:24 +08:00
struct mg_str body; // Body
struct mg_str message; // Request line + headers + body
2020-12-09 00:26:17 +08:00
};
```
2021-09-15 14:43:24 +08:00
Structure represents the HTTP message.
2022-06-02 19:02:26 +08:00
<img src="images/mg_http_message.svg" alt="HTTP message" />
2021-09-15 14:43:24 +08:00
2020-12-09 00:26:17 +08:00
### mg\_http\_listen()
```c
2021-09-15 20:37:57 +08:00
struct mg_connection *mg_http_listen(struct mg_mgr *mgr, const char *url,
2020-12-09 00:26:17 +08:00
mg_event_handler_t fn, void *fn_data);
```
Create HTTP listener.
2021-09-15 20:37:57 +08:00
Parameters:
- `mgr` - An event manager
- `url` - A URL, specifies local IP address and port to listen on, e.g. `http://0.0.0.0:8000`
- `fn` - An event handler function
- `fn_data` - An arbitrary pointer, which will be passed as `fn_data` when an
2020-12-09 00:26:17 +08:00
event handler is called. This pointer is also stored in a connection
structure as `c->fn_data`
Return value: Pointer to created connection or `NULL` in case of error
2021-09-15 20:37:57 +08:00
2021-09-15 14:43:24 +08:00
Usage example:
```c
struct mg_connection *c = mg_http_listen(&mgr, "0.0.0.0:8000", fn, arg);
if (c == NULL) fatal_error("Cannot create listener");
```
2020-12-09 00:26:17 +08:00
### mg\_http\_connect()
```c
struct mg_connection *mg_http_connect(struct mg_mgr *, const char *url,
mg_event_handler_t fn, void *fn_data);
```
Create HTTP client connection.
2021-09-15 20:37:57 +08:00
Note: This function does not connect to peer; it allocates required resources and
2021-09-15 20:37:57 +08:00
starts connect process. Once peer is really connected `MG_EV_CONNECT` event is
sent to connection event handler.
Parameters:
- `mgr` - An event manager
- `url` - A URL, specifies remote URL, e.g. `http://google.com`
- `fn` - An event handler function
- `fn_data` - An arbitrary pointer, which will be passed as `fn_data` when an
2020-12-09 00:26:17 +08:00
event handler is called. This pointer is also stored in a connection
structure as `c->fn_data`
Return value: Pointer to created connection or `NULL` in case of error
2021-09-15 14:43:24 +08:00
Usage example:
2020-12-09 00:26:17 +08:00
2021-09-15 14:43:24 +08:00
```c
struct mg_connection *c = mg_http_connect(&mgr, "http://google.com", fn, NULL);
if (c == NULL) fatal_error("Cannot create connection");
```
2020-12-09 00:26:17 +08:00
### mg\_http\_status()
```c
int mg_http_status(const struct mg_http_message *hm);
```
Get status code of the HTTP response.
Parameters:
- `hm` - Parsed HTTP response
Return value: status code, e.g. `200` for success.
2020-12-09 00:26:17 +08:00
### mg\_http\_get\_request\_len()
```c
int mg_http_get_request_len(const unsigned char *buf, size_t buf_len);
```
2021-09-15 20:37:57 +08:00
Get length of request.
2021-09-15 14:43:24 +08:00
The length of request is a number of bytes till the end of HTTP headers. It does
not include length of HTTP body.
2021-09-15 20:37:57 +08:00
Parameters:
- `buf` - A pointer to a buffer with request
- `buf_len` - Buffer length
2021-09-15 20:37:57 +08:00
Return value: -1 on error, 0 if a message is incomplete, or the length of request
2021-09-15 14:43:24 +08:00
Usage example:
```c
const char *buf = "GET /test \n\nGET /foo\n\n";
int req_len = mg_http_get_request_len(buf, strlen(buf)); // req_len == 12
```
2020-12-09 00:26:17 +08:00
2022-06-02 19:02:26 +08:00
<img src="images/mg_http_get_request_len.svg" alt="Function mg_http_get_request_len()" />
2020-12-09 00:26:17 +08:00
### mg\_http\_parse()
```c
int mg_http_parse(const char *s, size_t len, struct mg_http_message *hm);
```
2021-09-15 20:37:57 +08:00
Parse string request into `mg_http_message` structure
Parameters:
- `s` - A request string
- `len` - A request string length
- `hm` - A pointer to a structure to store parsed request
2021-09-15 20:37:57 +08:00
Return value: request length (see `mg_http_get_request_len()`)
2021-09-15 14:43:24 +08:00
Usage example:
2020-12-09 00:26:17 +08:00
2021-09-15 14:43:24 +08:00
```c
struct mg_http_message hm;
const char *buf = "GET / HTTP/1.0\n\n";
if (mg_http_parse(buf, strlen(buf), &hm) > 0) { /* success */ }
```
2020-12-09 00:26:17 +08:00
### mg\_http\_printf\_chunk()
2021-09-15 14:43:24 +08:00
```c
void mg_http_printf_chunk(struct mg_connection *c, const char *fmt, ...);
2020-12-09 00:26:17 +08:00
```
Write a chunk of data in chunked encoding format, using `printf()` semantic.
2021-09-15 20:37:57 +08:00
Parameters:
- `c` - A connection pointer
- `fmt` - A string, format specified in `printf` semantics
2021-09-15 20:37:57 +08:00
Return value: None
2021-09-15 20:37:57 +08:00
2021-09-15 14:43:24 +08:00
Usage example:
```c
mg_http_printf_chunk(c, "Hello, %s!", "world");
```
2020-12-09 00:26:17 +08:00
### mg\_http\_write\_chunk()
```c
void mg_http_write_chunk(struct mg_connection *c, const char *buf, size_t len);
```
Write a chunk of data in chunked encoding format.
2021-09-15 20:37:57 +08:00
Parameters:
- `c` - A connection pointer
- `buf` - Data to write
- `len` - Data length
2021-09-15 20:37:57 +08:00
Return value: None
2021-09-15 20:37:57 +08:00
2021-09-15 14:43:24 +08:00
Usage example:
```c
mg_http_write_chunk(c, "hi", 2);
```
### mg\_http\_delete\_chunk()
```c
void mg_http_delete_chunk(struct mg_connection *c, struct mg_http_message *hm);
```
2021-09-15 20:37:57 +08:00
Remove chunk specified from input buffer.
Parameters:
- `c` - A connection pointer
- `hm` - Chunk to delete
2021-09-15 20:37:57 +08:00
Return value: None
2021-09-15 14:43:24 +08:00
Usage example:
```c
// Mongoose events handler
void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
if (ev == MG_EV_HTTP_CHUNK) {
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
mg_http_delete_chunk(c, hm); // Remove received chunk
}
}
```
2020-12-09 00:26:17 +08:00
2022-06-01 06:44:03 +08:00
### struct mg\_http\_serve\_opts
2020-12-09 00:26:17 +08:00
```c
struct mg_http_serve_opts {
const char *root_dir; // Web root directory, must be non-NULL
2021-03-11 21:01:45 +08:00
const char *ssi_pattern; // SSI file name pattern, e.g. #.shtml
const char *extra_headers; // Extra HTTP headers to add in responses
2022-06-01 06:44:03 +08:00
const char *mime_types; // Extra mime types, ext1=type1,ext2=type2,..
const char *page404; // Path to the 404 page, or NULL by default
struct mg_fs *fs; // Filesystem implementation. Use NULL for POSIX
};
2022-06-01 06:44:03 +08:00
```
A structure passed to `mg_http_serve_dir()` and `mg_http_serve_file()`, which
drives the behavior of those two functions.
### mg\_http\_serve\_dir()
```c
2021-09-15 20:37:57 +08:00
void mg_http_serve_dir(struct mg_connection *c, struct mg_http_message *hm,
const struct mg_http_serve_opts *opts);
2020-12-09 00:26:17 +08:00
```
Serve static files according to the given options. Note that in order to
enable SSI, set a `-DMG_ENABLE_SSI=1` build flag.
2020-12-09 00:26:17 +08:00
2021-11-25 20:29:45 +08:00
<span class="badge bg-danger">NOTE: </span> Avoid double dots `..` in
the `root_dir`. If you need to
reference an upper-level directory, use absolute path.
2021-09-15 20:37:57 +08:00
Parameters:
- `c` - Connection to use
- `hm` - HTTP message, that should be served
- `opts` - Serve options. Note that `opts.root_dir` can optionally accept
2021-09-20 19:24:44 +08:00
extra comma-separated `uri=path` pairs, see example below
2021-09-15 20:37:57 +08:00
Return value: None
2021-09-15 20:37:57 +08:00
2021-09-15 14:43:24 +08:00
Usage example:
```c
// Mongoose events handler
void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
if (ev == MG_EV_HTTP_MSG) {
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
struct mg_http_serve_opts opts;
memset(&opts, 0, sizeof(opts));
2021-09-20 19:24:44 +08:00
opts.root_dir = "/var/www,/conf=/etc"; // Serve /var/www. URIs starting with /conf are served from /etc
2021-09-15 14:43:24 +08:00
mg_http_serve_dir(c, hm, &opts);
}
}
```
2020-12-09 00:26:17 +08:00
2021-01-12 18:28:41 +08:00
### mg\_http\_serve\_file()
2020-12-09 00:26:17 +08:00
```c
2021-09-15 20:37:57 +08:00
void mg_http_serve_file(struct mg_connection *c, struct mg_http_message *hm,
2021-07-29 21:21:20 +08:00
const char *path, struct mg_http_serve_opts *opts);
2020-12-09 00:26:17 +08:00
```
Serve static file.
<span class="badge bg-danger">NOTE: </span> `opts->root_dir` settings
is ignored by this function.
<span class="badge bg-danger">NOTE: </span> `opts->extra_headers`
must end with `\r\n`.
2021-09-15 14:43:24 +08:00
2021-09-15 20:37:57 +08:00
Parameters:
- `c` - Connection to use
- `hm` - HTTP message to serve
- `path` - Path to file to serve
- `opts` - Serve options
2021-09-15 20:37:57 +08:00
Return value: None
2021-09-15 20:37:57 +08:00
2021-09-15 14:43:24 +08:00
Usage example:
2021-01-08 00:21:01 +08:00
```c
2021-09-15 14:43:24 +08:00
// Mongoose events handler
void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
if (ev == MG_EV_HTTP_MSG) {
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
struct mg_http_serve_opts opts = {
.mime_types = "png=image/png",
.extra_headers = "AA: bb\r\nCC: dd\r\n"
};
mg_http_serve_file(c, hm, "a.png", &opts);
2021-09-15 14:43:24 +08:00
}
}
2021-01-08 00:21:01 +08:00
```
2020-12-09 00:26:17 +08:00
### mg\_http\_reply()
```c
2021-09-15 14:43:24 +08:00
void mg_http_reply(struct mg_connection *c, int status_code,
const char *headers, const char *body_fmt, ...);
2020-12-09 00:26:17 +08:00
```
2020-12-18 06:45:22 +08:00
Send simple HTTP response using `printf()` semantic. This function formats
response body according to a `body_fmt`, and automatically appends a correct
2021-09-15 14:43:24 +08:00
`Content-Length` header. Extra headers could be passed via `headers` parameter.
2020-12-18 06:45:22 +08:00
2021-09-15 20:37:57 +08:00
Parameters:
- `c` - Connection to use
- `status_code` - An HTTP response code
- `headers` - Extra headers, default NULL. If not NULL, must end with `\r\n`
- `fmt` - A format string for the HTTP body, in a printf semantics
2020-12-09 00:26:17 +08:00
Return value: None
2021-09-15 20:37:57 +08:00
2022-06-02 19:02:26 +08:00
<img src="images/mg_http_reply.svg" alt="Function mg_http_reply()" />
2021-07-30 20:19:20 +08:00
2021-09-15 14:43:24 +08:00
Usage examples:
2021-07-30 20:19:20 +08:00
2021-11-16 20:30:40 +08:00
Send a simple JSON response:
2021-09-15 14:43:24 +08:00
```c
mg_http_reply(c, 200, "Content-Type: application/json\r\n", "{\"result\": %d}", 123);
```
2021-07-30 20:19:20 +08:00
2022-06-24 21:24:14 +08:00
Send JSON response:
2021-09-15 14:43:24 +08:00
```c
2022-06-24 21:24:14 +08:00
char *json = mg_mprintf("{%Q:%d}", "name", 123);
mg_http_reply(c, 200, "Content-Type: application/json\r\n", "%s\n", json);
2021-09-15 14:43:24 +08:00
free(json);
```
Send a 302 redirect:
```c
mg_http_reply(c, 302, "Location: /\r\n", "");
```
Send error:
```c
mg_http_reply(c, 403, "", "%s", "Not Authorized\n");
```
2020-12-09 00:26:17 +08:00
2021-04-30 00:16:33 +08:00
### mg\_http\_get\_header()
2020-12-09 00:26:17 +08:00
```c
2021-09-15 20:37:57 +08:00
struct mg_str *mg_http_get_header(struct mg_http_message *hm, const char *name);
2020-12-09 00:26:17 +08:00
```
2021-09-15 20:37:57 +08:00
Get HTTP header value
Parameters:
- `hm` - HTTP message to look for header
- `name` - Header name
2021-09-15 20:37:57 +08:00
Return value: HTTP header value or `NULL` if not found
2021-09-15 14:43:24 +08:00
Usage example:
```c
// Mongoose event handler
void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
if (ev == MG_EV_HTTP_MSG) {
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
struct mg_str *s = mg_http_get_header(hm, "X-Extra-Header");
if (s != NULL) {
mg_http_reply(c, 200, "", "Holly molly! Header value: %.*s", (int) s->len, s->ptr);
} else {
mg_http_reply(c, 200, "", "Oh no, header is not set...");
}
}
}
```
2020-12-09 00:26:17 +08:00
2021-12-03 17:54:03 +08:00
### mg\_http\_get\_header\_var()
```c
struct mg_str mg_http_get_header_var(struct mg_str s, struct mg_str v);
```
Parse HTTP header (e.g. Cookie header) which has form
`name1=value1; name2=value2; ...` and fetch a given variable.
Parameters:
- `s` - HTTP header
- `name` - variable name name
Return value: a requested variable, or an empty string.
Usage example:
```c
struct mg_str *cookie = mg_http_get_header(hm, "Cookie");
struct mg_str token = mg_str("");
if (cookie != NULL) {
token = mg_http_get_header_var(*cookie, mg_str("access_token"));
}
```
2022-06-18 11:23:56 +08:00
### mg\_http\_var()
```c
struct mg_str mg_http_var(struct mg_str buf, struct mg_str name);
```
Fetch an undecoded HTTP variable. Parameters:
- `buf` - a url-encoded string: HTTP request body or query string
- `name` - a variable name to fetch
Return value: variable's value. If not found, it it a NULL string.
```c
// We have received a request to /my/uri?a=b&c=d%20
// The hm->query points to "a=b&c=d%20"
struct mg_str v = mg_http_var(hm->query, mg_str("c")); // v = "d%20"
```
2021-12-03 17:54:03 +08:00
2020-12-09 00:26:17 +08:00
### mg\_http\_get\_var()
```c
2021-09-15 20:37:57 +08:00
int mg_http_get_var(const struct mg_str *var, const char *name, char *buf, int len);
2020-12-09 00:26:17 +08:00
```
2022-06-18 11:23:56 +08:00
Fetch and decode an HTTP variable
2021-09-15 20:37:57 +08:00
Parameters:
- `var` - HTTP request body
- `name` - Variable name
- `buf` - Buffer to write decoded variable
- `len` - Buffer size
2021-09-15 20:37:57 +08:00
Return value: Length of decoded variable. A zero or negative value means error
2020-12-09 00:26:17 +08:00
2021-09-15 14:43:24 +08:00
Usage example:
2020-12-09 00:26:17 +08:00
```c
2021-09-15 14:43:24 +08:00
char buf[100] = "";
mg_http_get_var(&hm->body, "key1", buf, sizeof(buf)) {
2022-06-18 11:23:56 +08:00
...
}
2020-12-09 00:26:17 +08:00
```
### mg\_http\_creds()
```c
2021-09-15 20:37:57 +08:00
void mg_http_creds(struct mg_http_message *hm, char *user, size_t userlen,
2021-09-15 14:43:24 +08:00
char *pass, size_t passlen);
2020-12-09 00:26:17 +08:00
```
Fetch authentication credential from the request, and store into the
`user`, `userlen` and `pass`, `passlen` buffers. The credentials are looked
up in the following order:
- from the `Authorization` HTTP header,
- Basic auth fills both user and pass
- Bearer auth fills only pass
- from the `access_token` cookie, fills pass
- from the `?access_token=...` query string parameter, fills pass
If none is found, then both user and pass are set to empty nul-terminated strings.
2021-09-15 20:37:57 +08:00
Parameters:
- `hm` - HTTP message to look for credentials
- `user` - buffer to receive user name
- `userlen` - size of `user` buffer
- `pass` - buffer to receive password
- `passlen` - size of `pass` buffer
Return value: None
2021-09-15 20:37:57 +08:00
2021-09-15 14:43:24 +08:00
Usage example:
```c
// Mongoose events handler
void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
if (ev == MG_EV_HTTP_MSG) {
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
char user[100], pass[100];
mg_http_creds(hm, user, sizeof(user), pass, sizeof(pass)); // "user" is now user name and "pass" is now password from request
}
}
```
2020-12-09 00:26:17 +08:00
### mg\_http\_match\_uri()
```c
2021-09-15 20:37:57 +08:00
bool mg_http_match_uri(const struct mg_http_message *hm, const char *glob);
2020-12-09 00:26:17 +08:00
```
2021-09-15 20:37:57 +08:00
Check if HTTP request matches a given glob pattern.
Parameters:
- `hm` - HTTP message to match
- `glob` - Pattern
2021-09-15 20:37:57 +08:00
Return value: True if HTTP request matches a given glob pattern; false otherwise
2020-12-09 00:26:17 +08:00
2021-09-15 14:43:24 +08:00
Usage example:
```c
// Mongoose events handler
void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
if (ev == MG_EV_HTTP_MSG) {
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
if (mg_http_match_uri(hm, "/secret")) {
mg_http_reply(c, 200, NULL, "Very big secret!");
} else {
mg_http_reply(c, 200, NULL, "hello world..");
}
}
}
```
2020-12-09 00:26:17 +08:00
### mg\_http\_bauth()
```c
2021-09-15 20:37:57 +08:00
void mg_http_bauth(struct mg_connection *c, const char *user, const char *pass);
2020-12-09 00:26:17 +08:00
```
Write a Basic `Authorization` header to the output buffer.
2021-09-15 20:37:57 +08:00
Parameters:
- `c` - Connection to use
- `user` - User name
- `pass` - Password
2021-09-15 20:37:57 +08:00
Return value: None
2021-09-15 20:37:57 +08:00
2021-12-13 23:08:05 +08:00
Usage example which uses Basic auth to create Stripe subscription:
2021-09-15 14:43:24 +08:00
```c
2021-12-13 23:08:05 +08:00
mg_printf(c, "POST /v1/subscriptions HTTP/1.1\r\n"
"Host: api.stripe.com\r\n"
"Transfer-Encoding: chunked\r\n");
mg_http_bauth(c, stripe_private_key, NULL); // Add Basic auth header
mg_printf(c, "%s", "\r\n"); // End HTTP headers
mg_http_printf_chunk(c, "&customer=%s", customer_id); // Set customer
mg_http_printf_chunk(c, "&items[0][price]=%s", price); // And price
2021-12-13 23:14:29 +08:00
mg_http_printf_chunk(c, ""); // End request
2021-09-15 14:43:24 +08:00
```
2022-05-31 18:38:03 +08:00
### struct mg\_http\_part
2021-03-17 15:43:29 +08:00
```c
// Parameter for mg_http_next_multipart
struct mg_http_part {
struct mg_str name; // Form field name
struct mg_str filename; // Filename for file uploads
struct mg_str body; // Part contents
};
2021-09-15 14:43:24 +08:00
```
2021-03-17 15:43:29 +08:00
2022-05-31 18:38:03 +08:00
Structure that describes a single part of a HTTP multipart message.
2022-06-02 19:02:26 +08:00
<img src="images/mg_http_part.svg" alt="HTTP part" />
2022-05-31 18:38:03 +08:00
### mg\_http\_next\_multipart()
2021-09-15 14:43:24 +08:00
```c
2021-03-17 15:43:29 +08:00
size_t mg_http_next_multipart(struct mg_str body, size_t offset, struct mg_http_part *part);
```
Parse the multipart chunk in the `body` at a given `offset`. An initial
`offset` should be 0. Fill up parameters in the provided `part`, which could be
NULL. Return offset to the next chunk, or 0 if there are no more chunks.
2021-09-15 20:37:57 +08:00
Parameters:
- `body`- Message body
- `offset` - Start offset
- `part` - Pointer to `struct mg_http_part` to fill
2021-09-15 20:37:57 +08:00
Return value: offset to the next chunk, or 0 if there are no more chunks.
2022-06-04 15:29:03 +08:00
Usage example (or see [form upload tutorial](../tutorials/form-uploads/) ):
2021-09-15 14:43:24 +08:00
```c
struct mg_http_part part;
2022-06-04 15:29:03 +08:00
size_t pos = 0;
while ((pos = mg_http_next_multipart(body, pos, &part)) != 0) {
2021-09-15 14:43:24 +08:00
// Use part
}
```
2020-12-09 00:26:17 +08:00
2022-06-04 15:29:03 +08:00
A diagram below shows how `mg_http_next_multipart()` in action:
<img src="images/mg_http_next_multipart.svg" alt="Function mg_http_next_multipart()" />
2022-07-01 04:54:50 +08:00
### mg\_http\_upload()
```c
int mg_http_upload(struct mg_connection *c, struct mg_http_message *hm,
struct mg_fs *fs, const char *path, size_t max_size);
```
This is a helper utility function that is used to upload large files by small
chunks.
Append HTTP POST data to a file in a specified directory. A file name and
file offset are specified by the query string parameters:
`POST /upload?name=firmware.bin&offset=2048 HTTP/1.1`. If the offset is 0, then the
file is truncated. It is a client's responsibility to divide a file into a
smaller chunks and send a sequence of POST requests that will be handled by
this function.
Parameters:
- `c`- a connection
- `hm` - a parsed HTTP message
- `fs` - a filesystem where to write a file, e.g. `&mg_fs_posix`
- `path` - a filename
- `max_size` - a maximum allowed file size
Return value: file size after write, or negative number on error
Usage example:
```c
static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
if (ev == MG_EV_HTTP_MSG) {
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
if (mg_http_match_uri(hm, "/upload")) {
mg_http_upload(c, hm, &mg_fs_posix, "/tmp/myfile.bin", 99999);
} else {
struct mg_http_serve_opts opts = {.root_dir = "."}; // Serve
mg_http_serve_dir(c, ev_data, &opts); // static content
}
}
}
```
2020-12-09 00:26:17 +08:00
## Websocket
### struct mg\_ws\_message
```c
struct mg_ws_message {
2021-09-15 14:43:24 +08:00
struct mg_str data; // Websocket message data
uint8_t flags; // Websocket message flags
2020-12-09 00:26:17 +08:00
};
```
2021-09-15 14:43:24 +08:00
Structure represents the WebSocket message.
2020-12-09 00:26:17 +08:00
### mg\_ws\_connect()
```c
2021-09-15 20:37:57 +08:00
struct mg_connection *mg_ws_connect(struct mg_mgr *mgr, const char *url,
2020-12-09 00:26:17 +08:00
mg_event_handler_t fn, void *fn_data,
const char *fmt, ...);
```
Create client Websocket connection.
2021-09-15 20:37:57 +08:00
Note: this function does not connect to peer, it allocates required resources and
starts the connect process. Once peer is really connected, the `MG_EV_CONNECT` event is
2021-09-15 20:37:57 +08:00
sent to connection event handler.
Parameters:
- `mgr` - Event manager to use
- `url` - Specifies remote URL, e.g. `http://google.com`
2021-11-16 20:30:40 +08:00
- `opts` - MQTT options, with client ID, QoS, etc
- `fn` - An event handler function
- `fn_data` - An arbitrary pointer, which will be passed as `fn_data` when an
2020-12-09 00:26:17 +08:00
event handler is called. This pointer is also stored in a connection
structure as `c->fn_data`
- `fmt` - printf-like format string for additional HTTP headers, or NULL
Return value: Pointer to created connection or `NULL` on error
2021-09-15 14:43:24 +08:00
Usage example:
```c
struct mg_connection *c = mg_ws_connect(&mgr, "ws://test_ws_server.com:1000",
handler, NULL, "%s", "Sec-WebSocket-Protocol: echo\r\n");
if(c == NULL) fatal("Cannot create connection");
```
2020-12-09 00:26:17 +08:00
### mg\_ws\_upgrade()
```c
2021-09-15 20:37:57 +08:00
void mg_ws_upgrade(struct mg_connection *c, struct mg_http_message *,
const char *fmt, ...);
2020-12-09 00:26:17 +08:00
```
Upgrade given HTTP connection to Websocket. The `fmt` is a printf-like
format string for the extra HTTP headers returned to the client in a
Websocket handshake. Set `fmt` to `NULL` if no extra headers need to be passed.
2020-12-09 00:26:17 +08:00
2021-09-15 20:37:57 +08:00
Parameters:
- `c` - Connection to use
2021-09-15 20:37:57 +08:00
- `hm` - HTTP message
- `fmt` - printf-like format string for additional HTTP headers, or NULL
Return value: None
2021-09-15 20:37:57 +08:00
2021-09-15 14:43:24 +08:00
Usage example:
```c
// Mongoose events handler
void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
if (ev == MG_EV_HTTP_MSG) {
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
mg_ws_upgrade(c, hm, NULL); // Upgrade HTTP to WS
}
}
```
2020-12-09 00:26:17 +08:00
### mg\_ws\_send()
```c
2022-08-13 22:37:55 +08:00
size_t mg_ws_send(struct mg_connection *c, const void *buf, size_t len, int op);
2020-12-09 00:26:17 +08:00
```
2021-09-15 20:37:57 +08:00
Send data to websocket peer
Parameters:
- `c` - Connection to use
- `buf` - Data to send
- `len` - Data size
2021-09-15 20:37:57 +08:00
- `op` - Websocket message type
Return value: sent bytes count
Possible Websocket message type:
2020-12-09 00:26:17 +08:00
```c
#define WEBSOCKET_OP_CONTINUE 0
#define WEBSOCKET_OP_TEXT 1
#define WEBSOCKET_OP_BINARY 2
#define WEBSOCKET_OP_CLOSE 8
#define WEBSOCKET_OP_PING 9
#define WEBSOCKET_OP_PONG 10
```
2021-09-15 14:43:24 +08:00
Usage example:
```c
// Mongoose events handler
void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
if (ev == MG_EV_WS_OPEN) {
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
mg_ws_send(c, "opened", 6, WEBSOCKET_OP_BINARY); // Send "opened" to web socket connection
}
}
```
2022-07-21 22:46:50 +08:00
### mg\_ws\_printf(), mg\_ws\_vprintf()
```c
size_t mg_ws_printf(struct mg_connection *, int op, const char *fmt, ...);
2022-08-13 22:37:55 +08:00
size_t mg_ws_vprintf(struct mg_connection *, int op, const char *fmt, va_list *);
2022-07-21 22:46:50 +08:00
```
Same as `mg_ws_send()`, but formats data using `printf()` semantics.
<span class="badge bg-danger">NOTE: </span> See [mg\_ws\_send](#mg_ws_send)
for the list of possible Websocket message types
<span class="badge bg-danger">NOTE: </span> See [mg\_snprintf](#mg_snprintf-mg_vsnprintf)
for the list of supported format specifiers
Parameters:
- `c` - Connection to use
- `op` - Websocket message type
- `fmt` - format string in `printf` semantics
Return value: sent bytes count
Usage example:
```c
mg_ws_printf(c, WEBSOCKET_OP_TEXT, "Hello, %s!", "world");
```
2021-09-15 14:43:24 +08:00
### mg\_ws\_wrap()
```c
size_t mg_ws_wrap(struct mg_connection *c, size_t len, int op)
```
Convert data in output buffer to WebSocket format. Useful then implementing protocol over WebSocket
2021-11-16 17:54:36 +08:00
See [examples/mqtt-over-ws-client](https://github.com/cesanta/mongoose/tree/master/examples/mqtt-over-ws-client) for full example.
2021-09-15 14:43:24 +08:00
2021-09-15 20:37:57 +08:00
Parameters:
- `c` - Connection to use
- `len` - Bytes count to convert
2021-09-15 20:37:57 +08:00
- `op` - Websocket message type (see `mg_ws_send`)
Return value: New size of connection output buffer
2021-09-15 20:37:57 +08:00
2021-09-15 14:43:24 +08:00
Usage example:
```c
size_t len = c->send.len; // Store output buffer len
mg_mqtt_login(c, s_url, &opts); // Write MQTT login message
mg_ws_wrap(c, c->send.len - len, WEBSOCKET_OP_BINARY); // Wrap it into WS
```
## SNTP
### mg_sntp_connect()
```c
struct mg_connection *mg_sntp_connect(struct mg_mgr *mgr, const char *url,
mg_event_handler_t fn, void *fn_data)
```
2021-09-15 20:37:57 +08:00
Connect SNTP server.
Parameters:
- `mgr` - Event manager to use
- `url` - Specifies remote URL, `time.google.com` if NULL.
- `fn` - An event handler function
- `fn_data` - An arbitrary pointer, which will be passed as `fn_data` when an
2021-09-15 20:37:57 +08:00
event handler is called. This pointer is also stored in a connection
structure as `c->fn_data`
Return value: Pointer to created connection or `NULL` on error
2021-09-15 14:43:24 +08:00
Usage example:
```c
static void sntp_cb(struct mg_connection *c, int ev, void *evd, void *fnd) {
if (ev == MG_EV_SNTP_TIME) {
// Time received
struct timeval *tv = (struct timeval *tv)evd;
}
}
...
mg_sntp_connect(mgr&, NULL /* connect to time.google.com */, sntp_cb, NULL);
```
### mg_sntp_request()
2021-09-15 14:43:24 +08:00
```c
void mg_sntp_request(struct mg_connection *c)
2021-09-15 14:43:24 +08:00
```
Send time request to SNTP server
2021-09-15 20:37:57 +08:00
Parameters:
- `c` - Connection to use
2021-09-15 20:37:57 +08:00
Return value: None
2021-09-15 14:43:24 +08:00
Usage example:
```c
mg_sntp_request(c);
2021-09-15 14:43:24 +08:00
```
2020-12-09 00:26:17 +08:00
## MQTT
### struct mg\_mqtt\_opts
```c
struct mg_mqtt_opts {
2022-08-05 01:50:20 +08:00
struct mg_str user; // Username, can be empty
struct mg_str pass; // Password, can be empty
struct mg_str client_id; // Client ID
struct mg_str will_topic; // Will topic
struct mg_str will_message; // Will message
uint8_t will_qos; // Will message quality of service
uint8_t version; // Can be 4 (3.1.1), or 5. If 0, assume 4.
uint16_t keepalive; // Keep-alive timer in seconds
bool will_retain; // Retain last will
bool clean; // Use clean session, 0 or 1
2020-12-09 00:26:17 +08:00
};
```
2021-09-15 14:43:24 +08:00
Structure used to specify MQTT connection options.
2020-12-09 00:26:17 +08:00
### struct mg\_mqtt\_message
```c
struct mg_mqtt_message {
2022-08-05 01:50:20 +08:00
struct mg_str topic; // Parsed topic
struct mg_str data; // Parsed message
struct mg_str dgram; // Whole MQTT datagram, including headers
uint16_t id; // Set for PUBACK, PUBREC, PUBREL, PUBCOMP, SUBACK, PUBLISH
uint8_t cmd; // MQTT command, one of MQTT_CMD_*
uint8_t qos; // Quality of service
uint8_t ack; // Connack return code. 0 - success
2020-12-09 00:26:17 +08:00
};
```
2021-09-15 14:43:24 +08:00
Structure represents the MQTT message.
2020-12-09 00:26:17 +08:00
### mg\_mqtt\_connect()
```c
2021-09-15 20:37:57 +08:00
struct mg_connection *mg_mqtt_connect(struct mg_mgr *mgr, const char *url,
2020-12-09 00:26:17 +08:00
struct mg_mqtt_opts *opts,
mg_event_handler_t fn, void *fn_data);
```
Create client MQTT connection.
2021-09-15 20:37:57 +08:00
Note: This function does not connect to peer; it allocates required resources and
2021-09-15 20:37:57 +08:00
starts connect process. Once peer is really connected `MG_EV_CONNECT` event is
sent to connection event handler.
Parameters:
- `mgr` - Event manager to use
- `url` - Specifies remote URL, e.g. `http://google.com`
2020-12-09 00:26:17 +08:00
- `opts` - MQTT options, with client ID, qos, etc
- `fn` - An event handler function
- `fn_data` - An arbitrary pointer, which will be passed as `fn_data` when an
2020-12-09 00:26:17 +08:00
event handler is called. This pointer is also stored in a connection
structure as `c->fn_data`
2021-09-15 20:37:57 +08:00
Return value: pointer to created connection or `NULL` on error
2020-12-09 00:26:17 +08:00
2021-09-15 14:43:24 +08:00
Usage example:
2020-12-09 00:26:17 +08:00
```c
2021-09-15 14:43:24 +08:00
void fn(struct mg_connection *c, int ev, void *evd, void *fnd) {
char *buf = (char *) fnd;
if (ev == MG_EV_MQTT_OPEN) {
// Connection ready
}
}
2020-12-09 00:26:17 +08:00
2021-09-15 14:43:24 +08:00
mg_mqtt_connect(&mgr, "mqtt://test.org:1883", NULL, handler, NULL);
```
2020-12-09 00:26:17 +08:00
2021-09-15 14:43:24 +08:00
### mg\_mqtt\_listen()
2020-12-09 00:26:17 +08:00
```c
2021-09-15 14:43:24 +08:00
struct mg_connection *mg_mqtt_listen(struct mg_mgr *mgr, const char *url,
mg_event_handler_t fn, void *fn_data);
2020-12-09 00:26:17 +08:00
```
2021-09-15 14:43:24 +08:00
Create MQTT listener.
2021-09-15 20:37:57 +08:00
Parameters:
- `mgr` - Event manager to use
- `url` - Specifies local IP address and port to listen on, e.g. `mqtt://0.0.0.0:1883`
- `fn` - An event handler function
- `fn_data` - An arbitrary pointer, which will be passed as `fn_data` when an
2021-09-15 14:43:24 +08:00
event handler is called. This pointer is also stored in a connection
structure as `c->fn_data`
Return value: Pointer to created connection or `NULL` on error
2021-09-15 20:37:57 +08:00
2021-09-15 14:43:24 +08:00
Usage example:
```c
struct mg_connection *c = mg_mqtt_listen(&mgr, "0.0.0.0:1883", fn, arg);
if (c == NULL) fatal("Cannot create connection");
```
### mg\_mqtt\_login
```c
void mg_mqtt_login(struct mg_connection *c, const char *url,
struct mg_mqtt_opts *opts);
```
Send MQTT login request.
2021-09-15 20:37:57 +08:00
Parameters:
- `c` - Connection to use
- `url` - URL, containing user name and password to use
- `opts` - Request options
2021-09-15 20:37:57 +08:00
Return value: None
2021-09-15 20:37:57 +08:00
2021-09-15 14:43:24 +08:00
Usage example:
```c
// Mongoose events handler
void fn(struct mg_connection *c, int ev, void *evd, void *fnd) {
char *buf = (char *) fnd;
if (ev == MG_EV_MQTT_OPEN) {
struct mg_mqtt_opts opts = {.qos = 1,
.will_topic = mg_str("my topic"),
.will_message = mg_str("goodbye")};
mg_mqtt_login(c, s_url, &opts);
}
}
```
### mg\_mqtt\_pub()
```c
void mg_mqtt_pub(struct mg_connection *c, struct mg_str topic,
struct mg_str data, int qos, bool retain);
2021-09-15 14:43:24 +08:00
```
2021-09-15 20:37:57 +08:00
Publish message.
Parameters:
- `c` - Connection to use
- `topic` - Topic to publish data
- `data` - Data to publish
- `qos` - Required QoS
- `retain` - Retain flag
2021-09-15 20:37:57 +08:00
Return value: None
2021-09-15 14:43:24 +08:00
Usage example:
```c
mg_mqtt_pub(c, mg_str("topic"), mg_str("my data"), 1, false);
2021-09-15 14:43:24 +08:00
```
### mg\_mqtt\_sub()
```c
void mg_mqtt_sub(struct mg_connection *c, struct mg_str topic, int qos);
2021-09-15 14:43:24 +08:00
```
2021-09-15 20:37:57 +08:00
Subscribe to topic.
Parameters:
- `c` - Connection to use
- `topic` - Topic to subscribe
2021-11-16 20:30:40 +08:00
- `qos` - Required QoS
2021-09-15 20:37:57 +08:00
Return value: None
2021-09-15 14:43:24 +08:00
```c
mg_mqtt_sub(c, mg_str("my/topic"), 1);
2021-09-15 14:43:24 +08:00
```
2020-12-09 00:26:17 +08:00
2021-03-09 19:29:53 +08:00
### mg\_mqtt\_next\_sub()
```c
size_t mg_mqtt_next_sub(struct mg_mqtt_message *msg, struct mg_str *topic, uint8_t *qos, size_t pos);
2021-03-09 19:29:53 +08:00
```
2021-09-15 14:43:24 +08:00
Traverse list of subscribed topics.
2021-03-09 19:29:53 +08:00
Used to implement MQTT server when `MQTT_CMD_SUBSCRIBE` is received.
2021-09-15 20:37:57 +08:00
Initial position `pos` should be 4.
Parameters:
- `mgs` - MQTT message
- `topic` - Pointer to `mg_str` to receive topic
2021-11-16 20:30:40 +08:00
- `qos` - Pointer to `uint8_t` to receive QoS
- `pos` - Position to list from
2021-09-15 20:37:57 +08:00
Return value: Next position, or 0 when done
2021-03-09 19:29:53 +08:00
2021-09-15 14:43:24 +08:00
Usage example:
2021-03-09 19:29:53 +08:00
```c
2021-09-15 14:43:24 +08:00
// Mongoose events handler
void fn(struct mg_connection *c, int ev, void *evd, void *fnd) {
if (ev == MG_EV_MQTT_CMD) {
struct mg_mqtt_message *mm = (struct mg_mqtt_message *) ev_data;
if (mm->cmd == MQTT_CMD_SUBSCRIBE) {
size_t pos = 4;
uint8_t qos;
struct mg_str topic;
// Iterate over all subscribed topics
while ((pos = mg_mqtt_next_sub(mm, &topic, &qos, pos)) > 0) {
LOG(LL_INFO, ("SUB [%.*s]", (int) topic.len, topic.ptr));
}
2021-03-09 19:29:53 +08:00
}
}
}
```
### mg\_mqtt\_next\_unsub()
```c
size_t mg_mqtt_next_unsub(struct mg_mqtt_message *msg, struct mg_str *topic, size_t pos);
2021-03-09 19:29:53 +08:00
```
Same as `mg_mqtt_next_sub()`, but for unsubscribed topics. The difference
is that there is no QoS in unsubscribe request.
2021-09-15 20:37:57 +08:00
Parameters:
- `mgs` - MQTT message
- `topic` - Pointer to `mg_str` to receive topic
- `pos` - Position from which to list
2021-09-15 20:37:57 +08:00
Return value: Next position, or 0 when done
2021-09-15 20:37:57 +08:00
2021-09-15 14:43:24 +08:00
Usage example:
```c
// Mongoose events handler
void fn(struct mg_connection *c, int ev, void *evd, void *fnd) {
if (ev == MG_EV_MQTT_CMD) {
struct mg_mqtt_message *mm = (struct mg_mqtt_message *) ev_data;
if (mm->cmd == MQTT_CMD_UNSUBSCRIBE) {
size_t pos = 4;
struct mg_str topic;
if (mm->cmd == MQTT_CMD_UNSUBSCRIBE) {
// Iterate over all unsubscribed topics
while ((pos = mg_mqtt_next_unsub(mm, &topic, pos)) > 0) {
LOG(LL_INFO, ("SUB [%.*s]", (int) topic.len, topic.ptr));
}
}
}
}
}
```
### mg\_mqtt\_send_header()
```c
2021-09-15 20:37:57 +08:00
void mg_mqtt_send_header(struct mg_connection *c, uint8_t cmd, uint8_t flags, uint32_t len);
2021-09-15 14:43:24 +08:00
```
Send MQTT command header. Useful in MQTT server implementation. Command can be one of the following value:
```c
#define MQTT_CMD_CONNECT 1
#define MQTT_CMD_CONNACK 2
#define MQTT_CMD_PUBLISH 3
#define MQTT_CMD_PUBACK 4
#define MQTT_CMD_PUBREC 5
#define MQTT_CMD_PUBREL 6
#define MQTT_CMD_PUBCOMP 7
#define MQTT_CMD_SUBSCRIBE 8
#define MQTT_CMD_SUBACK 9
#define MQTT_CMD_UNSUBSCRIBE 10
#define MQTT_CMD_UNSUBACK 11
#define MQTT_CMD_PINGREQ 12
#define MQTT_CMD_PINGRESP 13
#define MQTT_CMD_DISCONNECT 14
```
2021-09-15 20:37:57 +08:00
Parameters:
- `c` - Connection to use
- `cmd` - Command (see above)
- `flags` - Command flags
- `len` - Size of the following command
2021-09-15 20:37:57 +08:00
Return value: None
2021-09-15 20:37:57 +08:00
2021-09-15 14:43:24 +08:00
Usage example:
```c
// Mongoose events handler
void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
if (ev == MG_EV_MQTT_CMD) {
struct mg_mqtt_message *mm = (struct mg_mqtt_message *) ev_data;
if (mm->cmd == MQTT_CMD_CONNECT) {
uint8_t response[] = {0, 0};
mg_mqtt_send_header(c, MQTT_CMD_CONNACK, 0, sizeof(response)); // Send acknowledgement
mg_send(c, response, sizeof(response));
}
}
}
```
### mg\_mqtt\_ping()
```c
2021-09-15 20:37:57 +08:00
void mg_mqtt_ping(struct mg_connection *c);
2021-09-15 14:43:24 +08:00
```
Send `MQTT_CMD_PINGREQ` command via `mg_mqtt_send_header`
2021-09-15 20:37:57 +08:00
Parameters:
- `c` - Connection to use
2021-09-15 20:37:57 +08:00
Return value: None
2021-09-15 20:37:57 +08:00
2021-09-15 14:43:24 +08:00
Usage example:
```c
// Send periodic pings to all WS connections
static void timer_fn(void *arg) {
struct mg_mgr *mgr = (struct mg_mgr *) arg;
for (struct mg_connection *c = mgr->conns; c != NULL; c = c->next) {
if (c->is_websocket) mg_mqtt_ping(c);
}
}
```
### mg_mqtt_parse
```c
int mg_mqtt_parse(const uint8_t *buf, size_t len, struct mg_mqtt_message *m);
```
2021-09-15 20:37:57 +08:00
Parse buffer and fill `mg_mqtt_message` structure if buffer contain MQTT message.
Parameters:
- `buf` - buffer with MQTT message to parse
- `len` - buffer size
- `m` - pointer to `mg_mqtt_message` structure to receive parsed message
Return value: `MQTT_OK` if message successfully parsed, `MQTT_INCOMPLETE` if message
isn't fully received and `MQTT_MALFORMED` if message has wrong format.
2021-09-15 14:43:24 +08:00
Usage example:
```c
// Iterate over all MQTT frames contained in buf, len
struct mg_mqtt_message mm;
while ((mg_mqtt_parse(buf, len, &mm)) == MQTT_OK) {
2021-09-15 14:43:24 +08:00
switch (mm.cmd) {
case MQTT_CMD_CONNACK:
...
}
buf += mm.dgram.len;
len -= mm.dgram.len;
}
```
2020-12-09 00:26:17 +08:00
## TLS
2021-08-28 15:21:29 +08:00
### struct mg\_tls\_opts
2020-12-09 00:26:17 +08:00
```c
struct mg_tls_opts {
const char *ca; // CA certificate file. For both listeners and clients
const char *crl; // Certificate Revocation List. For clients
2020-12-09 00:26:17 +08:00
const char *cert; // Certificate
const char *certkey; // Certificate key
const char *ciphers; // Cipher list
2021-01-30 21:03:11 +08:00
struct mg_str srvname; // If not empty, enables server name verification
struct mg_fs *fs; // FS API for reading certificate files
2020-12-09 00:26:17 +08:00
};
2021-08-28 15:21:29 +08:00
```
TLS initialisation structure:
- `ca` - Certificate Authority. Can be a filename or a string. Used to verify
a certificate that the other end sends to us. If NULL, then certificate checking
2021-08-28 15:21:29 +08:00
is disabled
- `crl` - Certificate Revocation List. Can be a filename or a string. Used to
verify a certificate that the other end sends to us. If NULL, then certificate
revocation checking is disabled
- `cert` - Our own certificate. Can be a filename, or a string. If NULL, then
2021-08-28 15:21:29 +08:00
we don't authenticate with the other peer
- `certkey` - A key for a `cert`. Sometimes, a certificate and its key are
2021-08-28 15:21:29 +08:00
bundled in a single .pem file, in which case the values for `cert` and
`certkey` could be the same
- `ciphers` - A list of allowed ciphers
- `srvname` - Enable server name verification
2021-08-28 15:21:29 +08:00
NOTE: if both `ca` and `cert` are set, then so-called two-way TLS is enabled,
when both sides authenticate with each other. Usually, server-side connections
set both `ca` and `cert`, whilst client-side - only `ca`.
### mg\_tls\_init()
```c
2021-09-15 14:43:24 +08:00
void mg_tls_init(struct mg_connection *c, struct mg_tls_opts *opts);
2020-12-09 00:26:17 +08:00
```
2021-01-30 21:03:11 +08:00
Initialise TLS on a given connection.
2020-12-09 00:26:17 +08:00
2021-09-15 14:43:24 +08:00
<span class="badge bg-danger">NOTE:</span> mbedTLS implementation uses `mg_random`
as RNG. The `mg_random` can be overridden by setting `MG_ENABLE_CUSTOM_RANDOM`
and defining your own `mg_random()` implementation.
2021-04-29 16:09:21 +08:00
2021-09-15 20:37:57 +08:00
Parameters:
- `c` - Connection, for which TLS should be initialized
2021-09-15 20:37:57 +08:00
- `opts` - TLS initialization parameters
Return value: None
2021-09-15 20:37:57 +08:00
2021-09-15 14:43:24 +08:00
Usage example:
2020-12-09 00:26:17 +08:00
2021-09-15 14:43:24 +08:00
```c
struct mg_tls_opts opts = {.cert = "ca.pem"};
mg_tls_init(c, &opts);
```
2020-12-09 00:26:17 +08:00
2021-09-15 14:43:24 +08:00
## Timer
2020-12-09 00:26:17 +08:00
### mg\_timer\_add()
```c
struct mg_timer *mg_timer_add(struct mg_mgr *mgr,
uint64_t period_ms, unsigned flags,
void (*fn)(void *), void *fn_data);
```
Setup a timer. This is a high-level timer API that allows to add a software
timer to the event manager. This function `calloc()`s a new timer and
adds it to the `mgr->timers` list. All added timers are polled when
`mg_mgr_poll()` is called, and called if expired.
<span class="badge bg-danger">NOTE: </span> Make sure that the timer
interval is equal or more to the `mg_mgr_poll()` timeout.
Parameters:
- `mgr` - Pointer to `mg_mgr` event manager structure
- `ms` - An interval in milliseconds
- `flags` - Timer flags bitmask, `MG_TIMER_REPEAT` and `MG_TIMER_RUN_NOW`
- `fn` - Function to invoke
- `fn_data` - Function argument
Return value: Pointer to created timer
Usage example:
```c
void timer_fn(void *data) {
// ...
}
mg_timer_add(mgr, 1000, MG_TIMER_REPEAT, timer_fn, NULL);
```
2020-12-09 00:26:17 +08:00
### struct mg\_timer
```c
struct mg_timer {
uint64_t period_ms; // Timer period in milliseconds
uint64_t expire; // Expiration timestamp in milliseconds
2021-12-22 05:50:18 +08:00
unsigned flags; // Possible flags values below
2022-05-15 21:29:34 +08:00
#define MG_TIMER_ONCE 0 // Call function once
#define MG_TIMER_REPEAT 1 // Call function periodically
2021-12-22 05:50:18 +08:00
#define MG_TIMER_RUN_NOW 2 // Call immediately when timer is set
2020-12-09 00:26:17 +08:00
void (*fn)(void *); // Function to call
2021-03-11 21:01:45 +08:00
void *arg; // Function argument
2022-05-15 21:29:34 +08:00
struct mg_timer *next; // Linkage
2020-12-09 00:26:17 +08:00
};
```
2021-08-22 17:51:40 +08:00
Timer structure. Describes a software timer. Timer granularity is the same
as the `mg_mgr_poll()` timeout argument in the main event loop.
2020-12-09 00:26:17 +08:00
### mg\_timer\_init()
```c
void mg_timer_init(struct mg_timer **head,
struct mg_timer *t, uint64_t period_ms, unsigned flags,
2021-09-15 14:43:24 +08:00
void (*fn)(void *), void *fn_data);
2020-12-09 00:26:17 +08:00
```
Setup a timer.
2021-09-15 20:37:57 +08:00
Parameters:
- `head` - Pointer to `mg_timer` list head
- `t` - Pointer to `mg_timer` that should be initialized
- `ms` - An interval in milliseconds
- `flags` - Timer flags bitmask, `MG_TIMER_REPEAT` and `MG_TIMER_RUN_NOW`
- `fn` - Function to invoke
- `fn_data` - Function argument
2020-12-09 00:26:17 +08:00
Return value: None
2020-12-09 00:26:17 +08:00
2021-09-15 14:43:24 +08:00
Usage example:
2020-12-09 00:26:17 +08:00
```c
2021-09-15 14:43:24 +08:00
void timer_fn(void *data) {
// ...
}
struct mg_timer timer, *head = NULL;
mg_timer_init(&head, &timer, 1000, MG_TIMER_REPEAT, timer_fn, NULL);
2020-12-09 00:26:17 +08:00
```
### mg\_timer\_free()
```c
void mg_timer_free(struct mg_timer **head, struct mg_timer *t);
2020-12-09 00:26:17 +08:00
```
2021-09-15 14:43:24 +08:00
Free timer, remove it from the internal timers list.
2021-09-15 20:37:57 +08:00
Parameters:
- `head` - Pointer to `mg_timer` list head
- `t` - Timer to free
2021-09-15 20:37:57 +08:00
Return value: None
2021-09-15 20:37:57 +08:00
2021-09-15 14:43:24 +08:00
Usage example:
```c
struct mg_timer timer;
// ...
mg_timer_free(&timer);
```
2020-12-09 00:26:17 +08:00
### mg\_timer\_poll()
```c
void mg_timer_poll(struct mg_timer **head, uint64_t uptime_ms);
2020-12-09 00:26:17 +08:00
```
Traverse list of timers and call them if current timestamp `uptime_ms` is
2020-12-09 00:26:17 +08:00
past the timer's expiration time.
Note, that `mg_mgr_poll` function internally calls `mg_timer_poll`; therefore,
2021-09-15 14:43:24 +08:00
in most cases it is unnecessary to call it explicitly.
2021-09-15 20:37:57 +08:00
Parameters:
- `head` - Pointer to `mg_timer` list head
2021-09-15 20:37:57 +08:00
- `uptime_ms` - current timestamp
Return value: None
2021-09-15 20:37:57 +08:00
2021-09-15 14:43:24 +08:00
Usage example:
```c
mg_timer_poll(mg_millis());
2021-09-15 14:43:24 +08:00
```
## Time
2021-08-28 15:46:01 +08:00
### mg\_millis()
```c
2021-12-22 05:50:18 +08:00
int64_t mg_millis(void);
2021-08-28 15:46:01 +08:00
```
Return current uptime in milliseconds.
Parameters: None
2021-09-15 20:37:57 +08:00
Return value: Current uptime
2021-09-15 20:37:57 +08:00
2021-09-15 14:43:24 +08:00
Usage example:
```c
2021-12-22 05:50:18 +08:00
int64_t uptime = mg_millis();
2021-09-15 14:43:24 +08:00
```
2021-08-28 15:46:01 +08:00
2021-08-28 13:54:56 +08:00
## String
2021-11-05 07:07:47 +08:00
### struct mg\_str
2021-08-28 13:54:56 +08:00
2021-11-05 07:07:47 +08:00
```c
2021-09-15 14:43:24 +08:00
struct mg_str {
const char *ptr; // Pointer to string data
size_t len; // String len
};
```
2021-08-28 13:54:56 +08:00
2021-11-05 07:07:47 +08:00
This structure represent an arbitrary chunk of memory, not necessarily
zero-terminated. This is a "mongoose string", and it gets used extensively
in the codebase instead of C zero-terminated strings.
For example, when an HTTP request is received, Mongoose created a
2021-11-16 20:30:40 +08:00
`struct mg_http_message` which has a collection of `struct mg_str` pointing
2021-11-05 07:07:47 +08:00
to request method, URI, headers, and so on. This way, Mongoose avoids
any heap allocations and does not modify the received buffer - instead, it
uses `struct mg_str` to describe various parts of HTTP request.
Same goes with many other cases.
NOTE: since `ptr` is not necessarily zero-terminated, do not use libc string
2021-11-16 20:30:40 +08:00
functions against it - like `strlen()` or `sscanf()`.
2021-08-28 13:54:56 +08:00
2021-09-15 14:43:24 +08:00
### mg\_str()
2021-08-28 13:54:56 +08:00
```c
2021-09-15 14:43:24 +08:00
struct mg_str mg_str(const char *s)
2021-08-28 13:54:56 +08:00
```
2021-09-15 14:43:24 +08:00
Create Mongoose string from NULL-terminated C-string. This function doesn't
duplicate provided string, and stores pointer within created `mg_str` structure.
Note, that is you have problems in C++ (constructor shadowing), there is `mg_str_s`
synonym for this function.
2021-08-28 13:54:56 +08:00
2021-09-15 20:37:57 +08:00
Parameters:
- `s` - Pointer to NULL-terminated string to store in created mg_str
2021-09-15 20:37:57 +08:00
Return value: Created Mongoose string
2021-09-15 20:37:57 +08:00
2021-09-15 14:43:24 +08:00
Usage example:
2021-08-28 13:54:56 +08:00
```c
2021-09-15 14:43:24 +08:00
struct mg_str str = mg_str("Hello, world!);
2021-08-28 13:54:56 +08:00
```
2021-09-15 14:43:24 +08:00
### mg\_str\_n()
2020-12-09 00:26:17 +08:00
```c
2021-09-15 14:43:24 +08:00
struct mg_str mg_str_n(const char *s, size_t n);
2020-12-09 00:26:17 +08:00
```
2021-11-16 20:30:40 +08:00
Create Mongoose string from C-string `s` (can be non-NULL terminated, length is
specified in `n`). Note: This function doesn't duplicate provided string,
but stores pointer within created `mg_str` structure.
2020-12-09 00:26:17 +08:00
2021-09-15 20:37:57 +08:00
Parameters:
- `s` - Pointer to string to store in created `mg_str`
2021-11-16 20:30:40 +08:00
- `n` - String length
2021-09-15 20:37:57 +08:00
Return value: Created Mongoose string
2021-09-15 20:37:57 +08:00
2021-09-15 14:43:24 +08:00
Usage example:
2020-12-09 00:26:17 +08:00
```c
2021-09-15 14:43:24 +08:00
struct mg_str str = mg_str_n("hi", 2);
2020-12-09 00:26:17 +08:00
```
2021-09-15 14:43:24 +08:00
### mg\_casecmp()
2020-12-09 00:26:17 +08:00
```c
2021-09-15 14:43:24 +08:00
int mg_casecmp(const char *s1, const char *s2);
2020-12-09 00:26:17 +08:00
```
2021-09-15 14:43:24 +08:00
Case insensitive compare two NULL-terminated strings.
2021-09-15 20:37:57 +08:00
Parameters:
- `s1`, `s2` - Pointers to strings to compare
2021-09-15 20:37:57 +08:00
Return value: Zero if strings are equal, more than zero if first argument is greater then second, and less than zero otherwise
2021-09-15 14:43:24 +08:00
Usage example:
2020-12-09 00:26:17 +08:00
2021-09-15 14:43:24 +08:00
```c
if (mg_casecmp("hello", "HELLO") == 0) {
// Strings are equal
}
```
2020-12-09 00:26:17 +08:00
2021-09-15 14:43:24 +08:00
### mg\_ncasecmp()
2020-12-09 00:26:17 +08:00
```c
2021-09-15 14:43:24 +08:00
int mg_ncasecmp(const char *s1, const char *s2, size_t len);
2020-12-09 00:26:17 +08:00
```
2021-09-15 14:43:24 +08:00
Case insensitive compare two C-strings, not more than `len` symbols or until meet `\0` symbol.
2020-12-09 00:26:17 +08:00
2021-09-15 20:37:57 +08:00
Parameters:
- `s1`, `s2` - Pointers to strings to compare
- `len` - Maximum length to compare
2021-09-15 20:37:57 +08:00
Return value: Zero if strings are equal, more than zero if first argument is
greater then second, and less than zero otherwise
2020-12-09 00:26:17 +08:00
2021-09-15 14:43:24 +08:00
Usage example:
2020-12-09 00:26:17 +08:00
```c
2021-09-15 14:43:24 +08:00
if (mg_ncasecmp("hello1", "HELLO2", 5) == 0) {
// Strings are equal
}
2020-12-09 00:26:17 +08:00
```
2021-09-15 14:43:24 +08:00
### mg\_vcmp()
2020-12-09 00:26:17 +08:00
```c
2021-09-15 14:43:24 +08:00
int mg_vcmp(const struct mg_str *s1, const char *s2);
2020-12-09 00:26:17 +08:00
```
2021-11-16 20:30:40 +08:00
Compare mongoose string and C-string.
2020-12-09 00:26:17 +08:00
2021-09-15 20:37:57 +08:00
Parameters:
- `s1` - Pointer to Mongoose string to compare
- `s2` - Pointer to C-string to compare
2021-09-15 20:37:57 +08:00
Return value: 0 if strings are equal, more than zero if first argument is
greater then second, and less than zero otherwise
2020-12-09 00:26:17 +08:00
2021-09-15 14:43:24 +08:00
Usage example:
2020-12-09 00:26:17 +08:00
2021-08-29 03:27:55 +08:00
```c
2021-09-15 14:43:24 +08:00
struct mg_str str = mg_str("hello");
if (mg_vcmp(str, "hello") == 0) {
// Strings are equal
}
2020-12-09 00:26:17 +08:00
```
2021-09-15 14:43:24 +08:00
### mg\_vcasecmp()
2020-12-09 00:26:17 +08:00
2021-08-29 03:27:55 +08:00
```c
2021-09-15 14:43:24 +08:00
int mg_vcasecmp(const struct mg_str *str1, const char *str2);
2020-12-09 00:26:17 +08:00
```
2021-09-15 14:43:24 +08:00
Case insensitive compare mongoose string and C-string.
2020-12-09 00:26:17 +08:00
2021-09-15 20:37:57 +08:00
Parameters:
- `str1` - Mongoose string to compare
- `str2` - C-string to compare
Return value: Zero if strings are equal, more than zero if first argument is
greater then second, and less than zero otherwise
2020-12-09 00:26:17 +08:00
2021-09-15 14:43:24 +08:00
Usage example:
2020-12-09 00:26:17 +08:00
```c
2021-09-15 14:43:24 +08:00
struct mg_str str = mg_str("hello");
if (mg_vcasecmp(str, "HELLO") == 0) {
// Strings are equal
}
2020-12-09 00:26:17 +08:00
```
2021-09-15 14:43:24 +08:00
### mg\_strcmp()
2021-08-28 14:16:38 +08:00
2021-09-15 14:43:24 +08:00
```c
int mg_strcmp(const struct mg_str str1, const struct mg_str str2);
```
2021-08-28 14:16:38 +08:00
2021-11-16 20:30:40 +08:00
Compare two mongoose strings.
2021-08-28 14:16:38 +08:00
2021-09-15 20:37:57 +08:00
Parameters:
- `str1`, `str2` - Pointers to Mongoose strings to compare
2021-09-15 20:37:57 +08:00
Return value: Zero if strings are equal, more than zero if first argument is
greater then second, and less than zero otherwise
2021-08-28 14:16:38 +08:00
2021-09-15 14:43:24 +08:00
Usage example:
2021-08-28 14:16:38 +08:00
```c
2021-09-15 14:43:24 +08:00
struct mg_str str1 = mg_str("hello");
struct mg_str str2 = mg_str("hello");
if (mg_strcmp(str1, str2) == 0) {
// Strings are equal
}
2021-08-28 14:16:38 +08:00
```
2021-09-15 14:43:24 +08:00
### mg\_strdup()
2021-08-28 14:16:38 +08:00
```c
2021-09-15 14:43:24 +08:00
struct mg_str mg_strdup(const struct mg_str s);
2021-08-28 14:16:38 +08:00
```
2021-09-15 14:43:24 +08:00
Duplicate provided string. Return new string or `MG_NULL_STR` on error.
Note: This function allocates memory for returned string. You may need to free it using `free` function.
2021-08-28 14:16:38 +08:00
2021-09-15 20:37:57 +08:00
Parameters:
- `s` - Mongoose string to duplicate
Return value: Duplicated string
2021-09-15 20:37:57 +08:00
2021-09-15 14:43:24 +08:00
Usage example:
2021-08-28 14:16:38 +08:00
```c
2021-09-15 14:43:24 +08:00
struct mg_str str1 = mg_str("hello");
struct mg_str str2 = mg_strdup(str1);
//...
free(str2.ptr);
2021-08-28 14:16:38 +08:00
```
2021-09-15 14:43:24 +08:00
### mg\_strstr()
2021-08-28 14:16:38 +08:00
```c
2021-09-15 14:43:24 +08:00
const char *mg_strstr(const struct mg_str haystack, const struct mg_str needle)
2021-08-28 14:16:38 +08:00
```
2021-09-15 20:37:57 +08:00
Search for `needle` substring in `haystack` string.
Parameters:
- `haystack` - Mongoose sting to search for substring
- `needle` - Mongoose string to search
Return value: pointer to `needle`
2021-09-15 14:43:24 +08:00
occurrence within `haystack` or `NULL` if not found.
Usage example:
2021-08-28 14:16:38 +08:00
2021-09-15 14:43:24 +08:00
```c
struct mg_str str = mg_str("Hello, world");
struct mg_str sub_str = mg_str("world");
2021-08-28 14:16:38 +08:00
2021-09-15 14:43:24 +08:00
if (mg_strstr(str, sub_str) != NULL) {
// Found
}
```
### mg\_strstrip()
2021-08-28 14:16:38 +08:00
```c
2021-09-15 14:43:24 +08:00
struct mg_str mg_strstrip(struct mg_str s)
2021-08-28 14:16:38 +08:00
```
2021-09-15 14:43:24 +08:00
Remove heading and trailing whitespace from mongoose string `s`.
2021-08-28 14:16:38 +08:00
2021-11-16 20:30:40 +08:00
Parameters:
2021-09-15 20:37:57 +08:00
- `s` - Mongoose string for trimming
Return value: Input string
2021-09-15 20:37:57 +08:00
2021-09-15 14:43:24 +08:00
Usage example:
2021-08-28 14:16:38 +08:00
2021-09-15 14:43:24 +08:00
```c
struct mg_str str = mg_strstrip(mg_str(" Hello, world "));
if (mg_vcmp(str, "Hello, world") == 0) {
// Strings are equal
}
```
### mg\_match()
2021-08-28 14:16:38 +08:00
```c
bool mg_match(struct mg_str str, struct mg_str pattern, struct mg_str *caps);
2021-08-28 14:16:38 +08:00
```
Check if string `str` matches glob pattern `pattern`, and optionally capture
wildcards into the provided array `caps`.
2022-01-29 19:11:22 +08:00
<span class="badge bg-danger">NOTE: </span> If `caps` is not NULL, then the
`caps` array size must be at least the number of wildcard symbols in `pattern`
2022-01-29 19:11:22 +08:00
plus 1. The last cap will be initialized to an empty string.
2022-01-29 19:12:31 +08:00
2021-09-15 14:43:24 +08:00
The glob pattern matching rules are as follows:
2021-08-28 14:16:38 +08:00
2021-09-15 14:43:24 +08:00
- `?` matches any single character
- `*` matches zero or more characters except `/`
- `#` matches zero or more characters
- any other character matches itself
2021-08-28 14:16:38 +08:00
2021-09-15 20:37:57 +08:00
Parameters:
- `str` - a string to match
- `pattern` - a pattern to match against
- `caps` - an optional array of captures for wildcard symbols `?`, `*`, '#'
2021-09-15 20:37:57 +08:00
Return value: `true` if matches, `false` otherwise
2021-09-15 20:37:57 +08:00
2021-09-15 14:43:24 +08:00
Usage example:
2020-12-09 00:26:17 +08:00
2021-08-28 15:46:01 +08:00
```c
// Assume that hm->uri holds /foo/bar. Then we can match the requested URI:
2022-01-29 19:11:22 +08:00
struct mg_str caps[3]; // Two wildcard symbols '*' plus 1
if (mg_match(hm->uri, mg_str("/*/*"), caps)) {
// caps[0] holds `foo`, caps[1] holds `bar`.
2021-09-15 14:43:24 +08:00
}
```
2021-08-28 15:46:01 +08:00
2021-09-15 14:43:24 +08:00
### mg\_commalist()
2021-08-28 15:46:01 +08:00
```c
2021-09-15 14:43:24 +08:00
bool mg_commalist(struct mg_str *s, struct mg_str *k, struct mg_str *v);
2020-12-09 00:26:17 +08:00
```
2021-09-15 14:43:24 +08:00
Parse string `s`, which is a comma-separated list of entries. An entry could be
either an arbitrary string, which gets stored in `v`, or a `KEY=VALUE` which
gets stored in `k` and `v` respectively.
2021-08-28 15:46:01 +08:00
IMPORTANT: This function modifies `s` by pointing to the next entry.
2020-12-09 00:26:17 +08:00
2021-09-15 20:37:57 +08:00
Parameters:
- `s` - String to search for entry
- `k` - Pointer to `mg_str` to receive entry key
- `v` - Pointer to `mg_str` to receive entry value
2021-09-15 20:37:57 +08:00
Return value: `true` if entry is found, `false` otherwise
2021-08-28 15:46:01 +08:00
Usage example:
2020-12-09 00:26:17 +08:00
```c
2021-09-15 14:43:24 +08:00
struct mg_str k, v, s = mg_str("a=333,b=777");
while (mg_commalist(&s, &k, &v)) // This loop output:
printf("[%.*s] set to [%.*s]\n", // [a] set to [333]
(int) k.len, k.ptr, (int) v.len, v.ptr); // [b] set to [777]
2020-12-09 00:26:17 +08:00
```
2022-06-08 18:01:30 +08:00
<img src="images/mg_commalist.svg" alt="Function mg_commalist()" />
2021-09-15 14:43:24 +08:00
### mg\_hex()
```c
char *mg_hex(const void *buf, size_t len, char *dst);
```
Hex-encode binary data `buf`, `len` into a buffer `dst` and nul-terminate it.
The output buffer must be at least 2 x `len` + 1 big.
2021-09-15 20:37:57 +08:00
Parameters:
- `buf` - Data to hex-encode
- `len` - Data length
- `dst` - Pointer to output buffer
2021-09-15 20:37:57 +08:00
Return value: `dst` pointer. The encoded characters are lowercase
2021-09-15 14:43:24 +08:00
Usage example:
```c
char data[] = "\x1\x2\x3";
char buf[sizeof(data)*2];
char *hex = mg_hex(data, sizeof(data) - 1, buf);
LOG(LL_INFO, ("%s", hex)); // Output "010203";
free(hex);
```
### mg\_unhex()
```c
void mg_unhex(const char *buf, size_t len, unsigned char *to);
```
Hex-decode string `buf`, `len` into a buffer `to`. The `to` buffer should be
at least `lsn` / 2 big.
2021-09-15 20:37:57 +08:00
Parameters:
- `buf` - Data to hex-decode
- `len` - Data length
- `to` - Pointer to output buffer
2021-09-15 20:37:57 +08:00
Return value: None
2021-09-15 20:37:57 +08:00
2021-09-15 14:43:24 +08:00
Usage example:
```c
char data[] = "010203";
char *buf[sizeof(data)/2];
char *hex = mg_unhex(data, sizeof(data) - 1, buf); // buf is now [1,2,3]
free(hex);
```
### mg\_unhexn()
```c
unsigned long mg_unhexn(const char *s, size_t len);
```
2021-09-15 20:37:57 +08:00
Parse `len` characters of the hex-encoded string `s`.
2021-09-15 14:43:24 +08:00
The maximum value of `len` is the width of the `long` x 2, for example
on 32-bit platforms it is 8.
2021-09-15 20:37:57 +08:00
Parameters:
- `s` - String to parse
- `len` - String length
2021-09-15 20:37:57 +08:00
Return value: Return parsed value
2021-09-15 20:37:57 +08:00
2021-09-15 14:43:24 +08:00
Usage example:
```c
char data[] = "010203";
char *buf[sizeof(data)/2];
unsigned long val = mg_unhex(data, sizeof(data) - 1); // val is now 123
```
### mg\_remove\_double\_dots()
```c
char *mg_remove_double_dots(char *s);
```
Modify string `s` in place by removing double dots from it. Used to
sanitize file names or URIs received from the network.
Parameters:
- `s` - String to sanitise
Return value: the `s` pointer
Usage example:
```c
char data[] = "../../a.txt";
mg_remove_double_dots(data); // data is /a.txt
```
2022-02-11 01:11:03 +08:00
### mg\_snprintf(), mg\_vsnprintf()
2021-09-15 14:43:24 +08:00
```c
2022-02-11 01:11:03 +08:00
size_t mg_snprintf(char *buf, size_t len, const char *fmt, ...);
size_t mg_vsnprintf(char *buf, size_t len, const char *fmt, va_list ap);
2021-09-15 14:43:24 +08:00
```
2022-02-11 01:11:03 +08:00
Print formatted string into a string buffer, just like `snprintf()`
standard function does, but in a predictable way that does not depend on
the C library or the build environment. The return value can be larger
than the buffer length `len`, in which case the overflow bytes are not printed.
Mongoose library is often used to exchange data in JSON format, therefore a
non-standard `%Q`, `%V`, `%H` specifiers for formatting JSON strings is also supported.
2021-09-15 14:43:24 +08:00
2021-09-15 20:37:57 +08:00
Parameters:
- `buf` - Pointer to pointer to output buffer
2022-02-11 01:11:03 +08:00
- `len` - Buffer size
2021-09-15 20:37:57 +08:00
- `fmt` - printf-like format string
2022-02-11 01:11:03 +08:00
Supported format specifiers:
- `hhd`, `hd`, `d`, `ld`, `lld` - for `char`, `short`, `int`, `long`, `int64_t`
- `hhu`, `hu`, `u`, `lu`, `llu` - same but for unsigned variants
- `hhx`, `hx`, `x`, `lx`, `llx` - same, unsigned and hex output
- `s` - expect `char *`
- `q` - expect `char *`, outputs JSON-escaped string (extension)
- `Q` - expect `char *`, outputs double-quoted JSON-escaped string (extension)
- `H` - expect `int`, `void *`, outputs double-quoted hex string (extension)
- `V` - expect `int`, `void *`, outputs double-quoted base64 string (extension)
- `M` - expect `size_t (*)(char, void *), void *ptr, va_list *)`, calls another print function (extension)
- `g`, `f` - expect `double`
- `c` - expect `char`
- `%` - expect `%` character itself
- `p` - expect any pointer, prints `0x.....` hex value
2022-02-11 01:11:03 +08:00
- `%X.Y` - optional width and precision modifiers
- `%.*` - optional precision modifier specified as `int` argument
2021-09-15 20:37:57 +08:00
Return value: Number of bytes printed
2021-09-15 20:37:57 +08:00
2022-06-10 20:01:52 +08:00
Sending JSON HTTP response:
```c
mg_http_reply(c, 200, "Content-Type: application/json\r\n",
"{%Q: %g}", "value", 1.2345);
```
Example of using more complex format strings:
2021-09-15 14:43:24 +08:00
2022-02-11 01:11:03 +08:00
```c
mg_snprintf(buf, sizeof(buf), "%lld", (int64_t) 123); // 123
mg_snprintf(buf, sizeof(buf), "%.2s", "abcdef"); // ab
mg_snprintf(buf, sizeof(buf), "%.*s", 2, "abcdef"); // ab
mg_snprintf(buf, sizeof(buf), "%05x", 123); // 00123
2022-02-11 19:02:06 +08:00
mg_snprintf(buf, sizeof(buf), "%%-%3s", "a"); // %- a
2022-06-10 16:38:36 +08:00
mg_snprintf(buf, sizeof(buf), "hi, %Q", "a"); // hi, "a"
mg_snprintf(buf, sizeof(buf), "r: %M, %d", f,1,2,7); // r: 3, 7
// Printing sub-function for %M specifier. Grabs two int parameters
size_t f(void (*out)(char, void *), void *ptr, va_list *ap) {
2022-06-10 16:38:36 +08:00
int a = va_arg(*ap, int);
int b = va_arg(*ap, int);
2022-08-14 03:34:20 +08:00
return mg_xprintf(out, ptr, "%d", a + b);
2022-06-10 16:38:36 +08:00
}
```
### mg\_mprintf(), mg\_vmprintf()
```c
char *mg_mprintf(const char *fmt, ...);
2022-08-13 22:37:55 +08:00
char *mg_vmprintf(const char *fmt, va_list *ap);
2022-06-10 16:38:36 +08:00
```
Print message into an allocated memory buffer. Caller must free the result.
Parameters:
- `fmt` - printf-like format string
Return value: allocated memory buffer
Usage example:
```c
char *msg = mg_mprintf("Double quoted string: %Q!", "hi");
free(msg);
2021-09-15 14:43:24 +08:00
```
### mg\_rprintf(), mg\_vrprintf()
```c
2022-08-14 03:34:20 +08:00
size_t mg_xprintf(void (*out)(char, void *), void *param, const char *fmt, ...);
size_t mg_vxprintf(void (*out)(char, void *), void *param, const char *fmt,
va_list *ap);
```
Print message using a specified character output function
Parameters:
- `out` - function to be used for printing chars
- `param` - argument to be passed to `out`
- `fmt` - printf-like format string
Return value: Number of bytes printed
Usage example:
```c
void myfn(char c, void *p);
2022-08-14 03:34:20 +08:00
size_t len = mg_xprintf(myfn, myfn_p, "Double quoted string: %Q!", "hi");
```
2022-08-05 04:04:11 +08:00
### mg\_pfn\_iobuf()
```c
void mg_pfn_iobuf(char ch, void *param);
```
Print a character to a [Generic IO buffer](#struct-mg_iobuf)
Parameters:
- `ch` - char to be printed
- `param` - must be `struct mg_iobuf *`
2022-08-05 04:04:11 +08:00
Usage example:
```c
2022-08-14 03:34:20 +08:00
mg_xprintf(mg_pfn_iobuf, &c->send, "hi!"); // Append to the output buffer
2022-08-05 04:04:11 +08:00
```
2021-09-15 14:43:24 +08:00
### mg\_to64()
```c
int64_t mg_to64(struct mg_str str);
2022-04-12 17:20:43 +08:00
uint64_t mg_tou64(struct mg_str str);
2021-09-15 14:43:24 +08:00
```
Parse 64-bit integer value held by string `s`.
2021-09-15 20:37:57 +08:00
Parameters:
- `str` - String to parse
2021-09-15 20:37:57 +08:00
Return value: Parsed value
2021-09-15 20:37:57 +08:00
2021-09-15 14:43:24 +08:00
Usage example:
```c
int64_t val = mg_to64(mg_str("123")); // Val is now 123
```
### mg\_aton()
```c
bool mg_aton(struct mg_str str, struct mg_addr *addr);
```
2021-09-15 20:37:57 +08:00
Parse IP address held by `str` and store it in `addr`.
Parameters:
- `str` - String to parse, for example `1.2.3.4`, `[::1]`, `01:02::03`
- `addr` - Pointer to `mg_addr` string to receive parsed value
2021-09-15 20:37:57 +08:00
Return value: `true` on success, `false` otherwise
2021-09-15 14:43:24 +08:00
Usage example:
```c
struct mg_addr addr;
if (mg_aton(mg_str("127.0.0.1"), &addr)) {
// addr is now binary representation of 127.0.0.1 IP address
}
```
### mg\_ntoa()
```c
char *mg_ntoa(const struct mg_addr *addr, char *buf, size_t len);
```
Stringify IP address `ipaddr` into a buffer `buf`, `len`
2021-09-15 20:37:57 +08:00
Parameters:
- `addr` - Address to stringify
- `buf` - Pointer to output buffer
- `len` - Output buffer size
2021-09-15 20:37:57 +08:00
Return value: `buf` value
2021-09-15 14:43:24 +08:00
Usage example:
```c
char buf[100];
mg_ntoa(&c->peer, buf, sizeof(buf));
```
2022-06-10 20:01:52 +08:00
## JSON
2022-08-05 04:04:11 +08:00
Note that Mongoose's printing functions support non-standard format specifiers `%Q` and `%M`,
2022-06-13 22:04:52 +08:00
which allow to print JSON strings easily:
```c
char *json = mg_mprintf("{%Q:%d}", "value", 123); // {"value":123}
free(json);
```
Therefore, for a full JSON support, a set of parsing functions is required -
which is described below.
2022-06-10 20:01:52 +08:00
### mg\_json\_get()
```c
enum { MG_JSON_TOO_DEEP = -1, MG_JSON_INVALID = -2, MG_JSON_NOT_FOUND = -3 };
2022-07-30 14:55:26 +08:00
int mg_json_get(struct mg_str json, const char *path, int *toklen);
2022-06-10 20:01:52 +08:00
```
2022-07-30 14:55:26 +08:00
Parse JSON string `json` and return the offset of the element
specified by the JSON `path`. The length of the element is stored
2022-06-10 20:01:52 +08:00
in the `toklen`.
Parameters:
2022-07-30 14:55:26 +08:00
- `json` - a string containing valid JSON
- `path` - a JSON path. Must start with `$`, e.g. `$.user`
- `toklen` - a pointer that receives element's length, can be NULL
2022-06-10 20:01:52 +08:00
Return value: offset of the element, or negative `MG_JSON_*` on error.
Usage example:
```c
2022-06-13 22:04:52 +08:00
// Create a json string: { "a": 1, "b": [2, 3] }
char *buf = mg_mprintf("{ %Q: %d, %Q: [%d, %d] }", "a", 1, "b", 2, 3);
2022-07-30 14:55:26 +08:00
struct mg_str json = mg_str(buf);
int offset, length;
2022-06-10 20:01:52 +08:00
// Lookup "$", which is the whole JSON. Can be used for validation
2022-07-30 14:55:26 +08:00
offset = mg_json_get(json, "$", &length); // offset = 0, length = 23
2022-06-10 20:01:52 +08:00
// Lookup attribute "a". Point to value "1"
2022-07-30 14:55:26 +08:00
offset = mg_json_get(json, "$.a", &length); // offset = 7, length = 1
2022-06-10 20:01:52 +08:00
// Lookup attribute "b". Point to array [2, 3]
2022-07-30 14:55:26 +08:00
offset = mg_json_get(json, "$.b", &length); // offset = 15, length = 6
2022-06-10 20:01:52 +08:00
// Lookup attribute "b[1]". Point to value "3"
2022-07-30 14:55:26 +08:00
offset = mg_json_get(json, "$.b[1]", &length); // offset = 19, length = 1
2022-06-13 22:04:52 +08:00
free(buf);
2022-06-10 20:01:52 +08:00
```
### mg\_json\_get\_num()
```c
bool mg_json_get_num(struct mg_str json, const char *path, double *v);
```
Fetch numeric (double) value from the json string `json` at JSON path
`path` into a placeholder `v`. Return true if successful.
Parameters:
- `json` - a string containing valid JSON
- `path` - a JSON path. Must start with `$`
- `v` - a placeholder for value
Return value: true on success, false on error
Usage example:
```c
double d = 0.0;
mg_json_get_num(mg_str("[1,2,3]", "$[1]", &d)); // d contains 2
mg_json_get_num(mg_str("{\"a\":1.23}", "$.a", &d)); // d contains 1.23
```
### mg\_json\_get\_bool()
```c
2022-06-15 01:19:25 +08:00
bool mg_json_get_bool(struct mg_str json, const char *path, bool *v);
2022-06-10 20:01:52 +08:00
```
Fetch boolean (bool) value from the json string `json` at JSON path
`path` into a placeholder `v`. Return true if successful.
Parameters:
- `json` - a string containing valid JSON
- `path` - a JSON path. Must start with `$`
- `v` - a placeholder for value
Return value: true on success, false on error
Usage example:
```c
bool b = false;
2022-06-15 01:19:25 +08:00
mg_json_get_bool(mg_str("[123]", "$[0]", &b)); // Error. b remains to be false
mg_json_get_bool(mg_str("[true]", "$[0]", &b)); // b is true
2022-06-10 20:01:52 +08:00
```
2022-07-01 03:03:02 +08:00
### mg\_json\_get\_long()
```c
2022-07-02 00:28:06 +08:00
long mg_json_get_long(struct mg_str json, const char *path, long default_val);
2022-07-01 03:03:02 +08:00
```
Fetch integer numeric (long) value from the json string `json` at JSON path
`path`. Return it if found, or `default_val` if not found.
Parameters:
- `json` - a string containing valid JSON
- `path` - a JSON path. Must start with `$`
- `default_val` - a default value for the failure case
Return value: found value, or `default_val` value
Usage example:
```c
2022-07-02 00:28:06 +08:00
long a = mg_json_get_long(mg_str("[123]", "$a", -1)); // a = -1
long b = mg_json_get_long(mg_str("[123]", "$[0]", -1)); // b = 123
2022-07-01 03:03:02 +08:00
```
2022-06-10 20:01:52 +08:00
### mg\_json\_get\_str()
```c
2022-06-15 01:19:25 +08:00
char *mg_json_get_str(struct mg_str json, const char *path);
2022-06-10 20:01:52 +08:00
```
Fetch string value from the json string `json` at JSON path
2022-06-15 01:19:25 +08:00
`path`. If found, a string is allocated using `calloc()`,
un-escaped, and returned to the caller. It is the caller's responsibility to
2022-06-10 20:01:52 +08:00
`free()` the returned string.
Parameters:
- `json` - a string containing valid JSON
- `path` - a JSON path. Must start with `$`
2022-06-15 01:19:25 +08:00
Return value: non-NULL on success, NULL on error
2022-06-10 20:01:52 +08:00
Usage example:
```c
2022-06-10 22:00:34 +08:00
struct mg_str json = mg_str("{\"a\": \"hi\"}"); // json = {"a": "hi"}
char *str = mg_json_get_str(json, "$.a"); // str = "hi"
2022-06-10 20:01:52 +08:00
free(str);
```
### mg\_json\_get\_hex()
```c
char *mg_json_get_hex(struct mg_str json, const char *path, int *len);
```
Fetch hex-encoded buffer from the json string `json` at JSON path
`path`. If found, a buffer is allocated using `calloc()`, decoded,
and returned to the caller. It is the caller's responsibility to
`free()` the returned string. Returned buffer is 0-terminated.
Parameters:
- `json` - a string containing valid JSON
- `path` - a JSON path. Must start with `$`
- `len` - a pointer that receives decoded length. Can be NULL
Return value: non-NULL on success, NULL on error
Usage example:
```c
struct mg_str json = mg_str("{\"a\": \"6869\"}"); // json = {"a": "6869"}
char *str = mg_json_get_hex(json, "$.a", NULL); // str = "hi"
free(str);
```
### mg\_json\_get\_b64()
```c
char *mg_json_get_b4(struct mg_str json, const char *path, int *len);
```
Fetch base64-encoded buffer from the json string `json` at JSON path
`path`. If found, a buffer is allocated using `calloc()`, decoded,
and returned to the caller. It is the caller's responsibility to
`free()` the returned string. Returned buffer is 0-terminated.
Parameters:
- `json` - a string containing valid JSON
- `path` - a JSON path. Must start with `$`
- `len` - a pointer that receives decoded length. Can be NULL
Return value: non-NULL on success, NULL on error
Usage example:
```c
struct mg_str json = mg_str("{\"a\": \"YWJj\"}"); // json = {"a": "YWJj"}
char *str = mg_json_get_b64(json, "$.a", NULL); // str = "abc"
free(str);
```
2022-08-05 04:04:11 +08:00
## RPC
Mongoose includes a set of functions to ease server-side processing by means of RPC methods.
### struct mg\_rpc
The RPC method handler structure. Each method has an entry in a linked list, each entry points to a string describing the pattern that will invoke it and the function that will be called to satisfy the method invocation, with a proper function argument.
```c
struct mg_rpc {
struct mg_rpc *next; // Next in list
struct mg_str method; // Method pattern
void (*fn)(struct mg_rpc_req *); // Handler function
void *fn_data; // Handler function argument
};
```
### struct mg\_rpc\_req
The RPC request descriptor. An invoked method receives a descriptor containing the request, and a pointer to a function to be called to print the output response, with a proper function argument; e.g.: [mg_pfn_realloc()](#mg_pfn_realloc) or [mg_pfn_iobuf()](#mg_pfn_iobuf)
```c
struct mg_rpc_req {
struct mg_rpc **head; // RPC handlers list head
struct mg_rpc *rpc; // RPC handler being called
mg_pfn_t pfn; // Response printing function
void *pfn_data; // Response printing function data
void *req_data; // Arbitrary request data
struct mg_str frame; // Request, e.g. {"id":1,"method":"add","params":[1,2]}
};
```
### mg\_rpc\_add()
```c
void mg_rpc_add(struct mg_rpc **head, struct mg_str method_pattern,
void (*handler)(struct mg_rpc_req *), void *handler_data);
```
Add the method `method_pattern` to the list `head` of RPC methods. Invoking this method will call `handler` and pass `handler_data` to it with the request (as `r->fn_data` in the usage example below).
Parameters:
- `head` - the linked list pointer
- `method_pattern` - the name of the method
- `handler` - the RPC function performing the action for this method
- `handler_data` - Arbitrary function data
Usage example:
```c
struct mg_rpc *s_rpc_head = NULL;
static void rpc_sum(struct mg_rpc_req *r) {
double a = 0.0, b = 0.0;
mg_json_get_num(r->frame, "$.params[0]", &a);
mg_json_get_num(r->frame, "$.params[1]", &b);
mg_rpc_ok(r, "%g", a + b);
}
static void rpc_mul(struct mg_rpc_req *r) {//...}
mg_rpc_add(&s_rpc_head, mg_str("sum"), rpc_sum, NULL);
mg_rpc_add(&s_rpc_head, mg_str("mul"), rpc_mul, NULL);
```
### mg\_rpc\_del()
```c
void mg_rpc_del(struct mg_rpc **head, void (*handler)(struct mg_rpc_req *));
```
Remove the method with RPC function handler `handler` from the list `head` of RPC methods.
Parameters:
- `head` - the linked list pointer
- `handler` - the RPC function performing the action for this method, use NULL to deallocate all
Usage example:
```c
struct mg_rpc *s_rpc_head = NULL;
// add methods
// ...
// Time to cleanup
mg_rpc_del(&s_rpc_head, rpc_mul); // Deallocate specific handler
mg_rpc_del(&s_rpc_head, NULL); // Deallocate all RPC handlers
```
### mg\_rpc\_process()
```c
void mg_rpc_process(struct mg_rpc_req *req);
```
Invoke the proper method for this request. If the requested method does not exist, `mg_rpc_err()` will be invoked and an error indication will be printed
Parameters:
- `req` - a request
Usage example:
```c
2022-08-10 22:35:07 +08:00
struct mg_rpc *s_rpcs = NULL; // Empty RPC list head
mg_rpc_add(&s_rpcs, mg_str("rpc.list"), mg_rpc_list, NULL); // Add rpc.list
// ... add more RPC methods
2022-08-05 04:04:11 +08:00
2022-08-10 22:35:07 +08:00
// On request, process the incoming frame
struct mg_str req = mg_str("{\"id\":1,\"method\":\"sum\",\"params\":[1,2]}");
struct mg_iobuf io = {0, 0, 0, 512}; // Empty IO buf, with 512 realloc granularity
2022-08-05 04:04:11 +08:00
struct mg_rpc_req r = {
2022-08-10 22:35:07 +08:00
.head = &s_rpcs, // RPC list head
.rpc = NULL, // This will be set by mg_rpc_process()
.pfn = mg_pfn_iobuf, // Printing function: print into the io buffer
.pfn_data = &io, // Pass our io buffer as a parameter
.req_data = NULL, // No specific request data
.frame = req, // Specify incoming frame
2022-08-05 04:04:11 +08:00
};
2022-08-10 22:35:07 +08:00
mg_rpc_process(&r);
if (io.buf != NULL) printf("Response: %s\n", (char *) io.buf);
mg_iobuf_free(&io);
2022-08-05 04:04:11 +08:00
```
### mg\_rpc\_ok(), mg\_rpc\_vok()
```c
void mg_rpc_ok(struct mg_rpc_req *, const char *fmt, ...);
void mg_rpc_vok(struct mg_rpc_req *, const char *fmt, va_list *ap);
```
Helper functions to print result frames
Parameters:
- `req` - a request
- `fmt` - printf-like format string
Usage example:
```c
static void rpc_sum(struct mg_rpc_req *r) {
double a = 0.0, b = 0.0;
mg_json_get_num(r->frame, "$.params[0]", &a);
mg_json_get_num(r->frame, "$.params[1]", &b);
mg_rpc_ok(r, "%g", a + b);
}
```
### mg\_rpc\_err(), mg\_rpc\_verr()
```c
void mg_rpc_err(struct mg_rpc_req *, int code, const char *fmt, ...);
void mg_rpc_verr(struct mg_rpc_req *, int code, const char *fmt, va_list *);
```
Helper functions to print error frames
Parameters:
- `req` - a request
- `fmt` - printf-like format string
Usage example:
```c
static void rpc_dosome(struct mg_rpc_req *r) {
...
mg_rpc_err(r, -32109, "\"%.*s not found\"", len, &r->frame.ptr[offset]);
}
```
### mg\_rpc\_list()
```c
void mg_rpc_list(struct mg_rpc_req *r);
```
Built-in RPC method to list all registered RPC methods. This function is not usually called directly, but registered as a method.
Parameters:
- `req` - a request
Usage example:
```c
mg_rpc_add(&s_rpc_head, mg_str("rpc.list"), mg_rpc_list, &s_rpc_head);
```
(see also [mg_rpc_add()](#mg_rpc_add))
2021-09-15 14:43:24 +08:00
## Utility
### mg\_call()
```c
void mg_call(struct mg_connection *c, int ev, void *ev_data);
```
Send `ev` event to `c` event handler. This function is useful then implementing
your own protocol.
2021-09-15 20:37:57 +08:00
Parameters:
- `c` - Connection to send event
- `ev` - Event to send
- `ev_data` - Additional event parameter
2021-09-15 20:37:57 +08:00
Return value: None
2021-09-15 20:37:57 +08:00
2021-09-15 14:43:24 +08:00
Usage example:
```c
// In a timer callback, send MG_EV_USER event to all connections
static void timer_fn(void *arg) {
struct mg_mgr *mgr = (struct mg_mgr *) arg;
for (struct mg_connection *c = mgr->conns; c != NULL; c = c->next) {
mg_call(c, MG_EV_USER, "hi!");
}
}
```
### mg\_error()
```c
void mg_error(struct mg_connection *c, const char *fmt, ...);
```
Send `MG_EV_ERROR` to connection event handler with error message formatted using printf semantics.
2021-09-15 20:37:57 +08:00
Parameters:
- `c` - Connection to send event
- `fmt` - Format string in `printf` semantics
2021-09-15 20:37:57 +08:00
Return value: None
2021-09-15 20:37:57 +08:00
2021-09-15 14:43:24 +08:00
Usage example:
```c
mg_error(c, "Operation failed, error code: %d", errno);
```
### mg\_md5\_init()
```c
void mg_md5_init(mg_md5_ctx *c);
```
Initialize context for MD5 hashing.
2021-09-15 20:37:57 +08:00
Parameters:
- `c` - Pointer to `mg_md5_ctx` structure to initialize
2021-09-15 20:37:57 +08:00
Return value: None
2021-09-15 20:37:57 +08:00
2021-09-15 14:43:24 +08:00
Usage example:
```c
mg_md5_ctx ctx;
mg_md5_init(&ctx);
```
### mg\_md5\_update()
```c
void mg_md5_update(mg_md5_ctx *c, const unsigned char *data, size_t len);
```
Hash `len` bytes of data pointed by `data` using MD5 algorithm.
2021-09-15 20:37:57 +08:00
Parameters:
- `c` - MD5 context
- `data` - Data to hash
- `len` - Data length
2021-09-15 20:37:57 +08:00
Return value: None
2021-09-15 20:37:57 +08:00
2021-09-15 14:43:24 +08:00
Usage example:
```c
mg_md5_ctx ctx;
// Context initialization
// ...
mg_md5_update(&ctx, "data", 4); // hash "data" string
mg_md5_update(&ctx, "more data", 9); // hash "more data" string
```
### mg\_md5\_final()
```c
2021-09-15 20:37:57 +08:00
void mg_md5_final(mg_md5_ctx *c, unsigned char buf[16]);
2021-09-15 14:43:24 +08:00
```
Get current MD5 hash for context.
2021-09-15 20:37:57 +08:00
Parameters:
- `c` - MD5 context
- `buf` - Pointer to buffer to write MD5 hash value
2021-09-15 20:37:57 +08:00
Return value: None
2021-09-15 20:37:57 +08:00
2021-09-15 14:43:24 +08:00
Usage example:
```c
mg_md5_ctx ctx;
// Context initialization
// ...
unsigned char buf[16];
mg_md5_final(&ctx, buf); // `buf` is now MD5 hash
```
### mg\_sha1\_init()
```c
2021-09-15 20:37:57 +08:00
void mg_sha1_init(mg_sha1_ctx *c);
2021-09-15 14:43:24 +08:00
```
Initialize context for calculating SHA1 hash
2021-09-15 20:37:57 +08:00
Parameters:
- `c` - pointer to `mg_sha1_ctx` structure to initialize
Return value: none
2021-09-15 14:43:24 +08:00
Usage example:
```c
mg_sha1_ctx ctx;
mg_sha1_init(&ctx);
```
### mg\_sha1\_update()
```c
2021-09-15 20:37:57 +08:00
void mg_sha1_update(mg_sha1_ctx *c, const unsigned char *data, size_t len);
2021-09-15 14:43:24 +08:00
```
Hash `len` bytes of `data` using SHA1 algorithm.
2021-09-15 20:37:57 +08:00
Parameters:
2021-11-16 20:30:40 +08:00
- `c` - SHA1 context
- `data` - Data to hash
- `len` - Data length
2021-09-15 20:37:57 +08:00
Return value: None
2021-09-15 20:37:57 +08:00
2021-09-15 14:43:24 +08:00
Usage example:
```c
mg_sha1_ctx ctx;
// Context initialization
// ...
mg_sha1_update(&ctx, "data", 4); // hash "data" string
mg_sha1_update(&ctx, "more data", 9); // hash "more data" string
```
### mg\_sha1\_final()
```c
2021-09-15 20:37:57 +08:00
void mg_sha1_final(unsigned char digest[20], mg_sha1_ctx *c);
2021-09-15 14:43:24 +08:00
```
Get current SHA1 hash for context.
2021-09-15 20:37:57 +08:00
Parameters:
- `c` - SHA1 context
- `digest` - Pointer to buffer to receive hash value
2021-09-15 20:37:57 +08:00
Return value: None
2021-09-15 20:37:57 +08:00
2021-09-15 14:43:24 +08:00
Usage example:
```c
mg_sha1_ctx ctx;
// Context initialization
// ...
unsigned char buf[20];
mg_sha1_final(buf, &ctx); // `buf` is now SHA1 hash
```
### mg\_base64\_update()
```c
int mg_base64_update(unsigned char p, char *out, int pos);
```
Encode `p` byte to base64 and write result into `out` buffer starting with `pos` position.
2021-09-15 20:37:57 +08:00
Parameters:
- `p` - Byte to encode
- `out` - Pointer to buffer to write result
- `pos` - Position in output buffer to write result
2021-09-15 20:37:57 +08:00
2021-11-16 20:30:40 +08:00
Return value: New position for further operations
2021-09-15 14:43:24 +08:00
Usage example:
```c
char buf[10];
mg_base64_update((unsigned char)"a", buf, 0); // Encode "a" into base64 and write it to the beginning of buf
```
### mg\_base64\_final()
```c
int mg_base64_final(char *buf, int pos);
```
Add base64 finish mark and `\0` symbol to `buf` at `pos` position.
2021-09-15 20:37:57 +08:00
Parameters:
- `buf` - Pointer to buffer to write finish mark
- `pos` - Position to write
2021-09-15 20:37:57 +08:00
2021-11-16 20:30:40 +08:00
Return value: New position for further operations
2021-09-15 20:37:57 +08:00
2021-09-15 14:43:24 +08:00
```c
char buf[10];
int pos;
// ...
mg_base64_final(buf, pos);
```
### mg\_base64\_encode()
```c
int mg_base64_encode(const unsigned char *p, int n, char *to);
```
2021-09-15 20:37:57 +08:00
Encode `n` bytes data pointed by `p` using base64 and write result into `to`.
Parameters:
- `p` - Pointer to data to encode
- `n` - Data length
- `to` - Pointer to buffer to write result
2021-09-15 20:37:57 +08:00
Return value: Written symbols number
2021-09-15 14:43:24 +08:00
Usage example:
```c
char buf[128];
mg_base64_encode((uint8_t *) "abcde", 5, buf); // buf is now YWJjZGU=
```
### mg\_base64\_decode()
```c
int mg_base64_decode(const char *src, int n, char *dst);
```
2021-09-15 20:37:57 +08:00
Decode `n` bytes of base64-ed `src` and write it to `dst`.
Parameters:
- `src` - Data to decode
- `n` - Data length
- `dst` - Pointer to output buffer
2021-09-15 20:37:57 +08:00
Return value: Number of written symbols.
2021-09-15 14:43:24 +08:00
Usage example:
```c
char buf[128];
mg_base64_decode("Q2VzYW50YQ==", 12, buf); // buf is now "Cesanta"
```
### mg\_random()
```c
void mg_random(void *buf, size_t len);
```
Fill in buffer `buf`, `len` with random data. Note: Mongoose uses this
function for TLS and some other routines that require RNG (random number
generator). It is possible to override a built-in `mg_random()` by specifying
a `MG_ENABLE_CUSTOM_RANDOM=1` build preprocessor constant.
2021-09-15 20:37:57 +08:00
Parameters:
- `buf` - Pointer to buffer to receive random data
- `len` - Buffer size
2021-09-15 20:37:57 +08:00
Return value: None
2021-09-15 20:37:57 +08:00
2021-09-15 14:43:24 +08:00
Usage example:
```c
char buf[10];
mg_random(buf, sizeof(buf)); // `buf` is now random bytes
```
### mg\_random\_str()
```c
char *mg_random_str(char *buf, size_t len);
```
Fill in buffer `buf`, `len` with random alphanumeric characters: `a-zA-Z0-9`.
A buffer is zero-terminated.
Parameters:
- `buf` - a pointer to a buffer
- `len` - a buffer size
Return value: `buf` value.
Usage example:
```c
char buf[10];
printf("Random: %s\n", mg_random_str(buf, sizeof(buf)));
```
2021-09-15 14:43:24 +08:00
### mg\_ntohs()
```c
uint16_t mg_ntohs(uint16_t net);
```
Convert `uint16_t` value to host order.
2021-09-15 20:37:57 +08:00
Parameters:
- `net` - 16-bit value in network order
Return value: 16-bit value in host order
2021-09-15 14:43:24 +08:00
Usage example:
```c
uint16_t val = mg_ntohs(0x1234);
```
### mg\_ntohl()
```c
uint32_t mg_ntohl(uint32_t net);
```
Convert `uint32_t` value to host order.
2021-09-15 20:37:57 +08:00
Parameters:
- `net` - 32-bit value in network order
Return value: 32-bit value in host order
2021-09-15 14:43:24 +08:00
Usage example:
```c
uint32_t val = mg_ntohl(0x12345678);
```
### mg\_ntohs()
```c
2021-09-15 20:37:57 +08:00
uint16_t mg_htons(uint16_t h);
2021-09-15 14:43:24 +08:00
```
Convert `uint16_t` value to network order.
2021-09-15 20:37:57 +08:00
Parameters:
- `h` - 16-bit value in host order
Return value: 16-bit value in network order
2021-09-15 14:43:24 +08:00
Usage example:
```c
uint16_t val = mg_htons(0x1234);
```
### mg\_htonl()
```c
2021-09-15 20:37:57 +08:00
uint32_t mg_ntohl(uint32_t h);
2021-09-15 14:43:24 +08:00
```
Convert `uint32_t` value to network order.
2021-09-15 20:37:57 +08:00
Parameters:
- `h` - 32-bit value in host order
Return value: 32-bit value in network order
2021-09-15 14:43:24 +08:00
Usage example:
```c
uint32_t val = mg_htonl(0x12345678);
```
### mg\_crc32()
```c
uint32_t mg_crc32(uint32_t crc, const char *buf, size_t len);
```
Calculate CRC32 checksum for a given buffer. An initial `crc` value should be `0`.
2021-09-15 20:37:57 +08:00
Parameters:
2021-11-16 20:30:40 +08:00
- `crc` - Initial CRC value
- `buf` - Data to calculate CRC32
- `len` - Data size
2021-09-15 20:37:57 +08:00
Return value: Calculated CRC32 checksum
2021-09-15 20:37:57 +08:00
2021-09-15 14:43:24 +08:00
Usage example:
```c
char data[] = "hello";
uint32_t crc = mg_crc32(0, data, sizeof(data));
```
### mg\_check\_ip\_acl()
```c
int mg_check_ip_acl(struct mg_str acl, uint32_t remote_ip);
```
Check IPv4 address `remote_ip` against the IP ACL `acl`. Parameters:
2021-09-15 20:37:57 +08:00
Parameters:
2021-09-15 14:43:24 +08:00
- `acl` - an ACL string, e.g. `-0.0.0.0/0,+1.2.3.4`
- `remote_ip` - IPv4 address in network byte order
Return value: 1 if `remote_ip` is allowed, 0 if not, and <0 if `acl` is invalid
2021-09-15 14:43:24 +08:00
Usage example:
```c
if (mg_check_ip_acl(mg_str("-0.0.0.0/0,+1.2.3.4"), c->peer.ip) != 1) {
LOG(LL_INFO, ("NOT ALLOWED!"));
}
```
### mg\_url\_decode()
```c
int mg_url_decode(const char *s, size_t n, char *to, size_t to_len, int form);
```
Decode URL-encoded string `s` and write it into `to` buffer.
2021-09-15 20:37:57 +08:00
Parameters:
- `s` - String to encode
2021-11-16 20:30:40 +08:00
- `n` - String to encode length
- `to` - Pointer to output buffer
- `to_len` - Output buffer size
- `form` - If non-zero, then `+` is decoded as whitespace.
2021-09-15 20:37:57 +08:00
Return value: Decoded bytes count or negative value on error
2021-09-15 14:43:24 +08:00
Usage example:
```c
char url[] = "eexample.org%2Ftest";
char buf[1024];
mg_url_encode(url, sizeof(url) - 1, buf, sizeof(buf), 0); // buf is now "example.org/test"
```
### mg\_url\_encode
```c
size_t mg_url_encode(const char *s, size_t n, char *buf, size_t len);
```
Encode `s` string to URL-encoding and write encoded string into `buf`.
2021-09-15 20:37:57 +08:00
Parameters:
- `s` - String to encode
- `n` - String to encode length
- `buf` - Output buffer
- `len` - Output buffer size
2021-09-15 20:37:57 +08:00
Return value: Number of characters written to `buf`
2021-09-15 14:43:24 +08:00
Usage example:
```c
char url[] = "example.org/test";
char buf[1024];
mg_url_encode(url, sizeof(url) - 1, buf, sizeof(buf)); // buf is now "example.org%2Ftest"
```
## IO Buffers
IO buffer, described by the `struct mg_iobuf`, is a simple data structure
that inserts or deletes chunks of data at arbitrary offsets and grows/shrinks
2021-08-30 20:06:45 +08:00
automatically.
2021-08-28 15:46:01 +08:00
### struct mg\_iobuf
2020-12-09 00:26:17 +08:00
2021-08-28 15:46:01 +08:00
```c
struct mg_iobuf {
2021-08-30 20:06:45 +08:00
unsigned char *buf; // Pointer to stored data
size_t size; // Total size available
size_t len; // Current number of bytes
2022-08-01 19:53:25 +08:00
size_t align; // Alignment during allocation
2021-08-28 15:46:01 +08:00
};
```
Generic IO buffer. The `size` specifies an allocation size of the data pointed
by `buf`, and `len` specifies number of bytes currently stored.
2022-05-25 01:56:54 +08:00
<img src="images/mg_iobuf.svg" alt="struct mg_iobuf diagram" />
2021-09-15 14:43:24 +08:00
2021-08-28 15:46:01 +08:00
### mg\_iobuf\_init()
2020-12-09 00:26:17 +08:00
```c
2022-08-01 19:53:25 +08:00
int mg_iobuf_init(struct mg_iobuf *io, size_t size, size_t align);
2020-12-09 00:26:17 +08:00
```
2021-09-15 20:37:57 +08:00
Initialize IO buffer, allocate `size` bytes.
Parameters:
- `io` - Pointer to `mg_iobuf` structure to initialize
- `size` - Amount of bytes to allocate
2022-08-01 19:53:25 +08:00
- `align` - Align `size` to the `align` mem boundary. `0` means no alignment
2021-09-15 20:37:57 +08:00
Return value: 1 on success, 0 on allocation failure
2021-09-15 14:43:24 +08:00
Usage example:
```c
struct mg_iobuf io;
2022-08-01 19:53:25 +08:00
if (mg_iobuf_init(&io, 0, 64)) {
2021-09-15 14:43:24 +08:00
// io successfully initialized
}
```
2021-08-28 15:46:01 +08:00
### mg\_iobuf\_resize()
```c
2021-08-28 15:46:01 +08:00
int mg_iobuf_resize(struct mg_iobuf *io, size_t size);
```
2021-08-28 15:46:01 +08:00
Resize IO buffer, set the new size to `size`. The `io->buf` pointer could
change after this, for example if the buffer grows. If `size` is 0, then the
`io->buf` is freed and set to NULL, and both `size` and `len` are set to 0.
2022-08-01 19:53:25 +08:00
The resulting `io->size` is always aligned to the `io->align` byte boundary;
therefore, to avoid memory fragmentation and frequent reallocations, set
`io->align` to a higher value.
2021-09-15 20:37:57 +08:00
Parameters:
- `io` - iobuf to resize
- `size` - New size
2021-09-15 20:37:57 +08:00
Return value: 1 on success, 0 on allocation failure
2021-08-25 14:59:31 +08:00
2021-09-15 14:43:24 +08:00
Usage example:
```c
struct mg_iobuf io;
2022-08-01 19:53:25 +08:00
mg_iobuf_init(&io, 0, 10); // An empty buffer with 10-byte alignment
2021-09-15 14:43:24 +08:00
2022-08-01 19:53:25 +08:00
if (mg_iobuf_resize(&io, 1)) {
// New io size is 10
2021-09-15 14:43:24 +08:00
}
```
2021-08-28 15:46:01 +08:00
### mg\_iobuf\_free()
2021-08-25 14:59:31 +08:00
```c
2021-08-28 15:46:01 +08:00
void mg_iobuf_free(struct mg_iobuf *io);
2021-08-25 14:59:31 +08:00
```
2021-09-15 14:43:24 +08:00
Free memory pointed by `io->buf` and set to NULL. Both `size` and `len` are set to 0.
2021-09-15 20:37:57 +08:00
Parameters:
- `io` - iobuf to free
Return value: None
2021-09-15 20:37:57 +08:00
2021-09-15 14:43:24 +08:00
Usage example:
```c
struct mg_iobuf io;
// IO buffer initialization
// ...
2021-08-25 14:59:31 +08:00
2021-09-15 14:43:24 +08:00
// Time to cleanup
mg_iobuf_free(&io);
```
2021-08-25 14:59:31 +08:00
2021-08-28 15:46:01 +08:00
### mg\_iobuf\_add()
2021-08-25 14:59:31 +08:00
2021-08-28 15:46:01 +08:00
```c
2022-08-01 19:53:25 +08:00
size_t mg_iobuf_add(struct mg_iobuf *io, size_t offset, const void *buf, size_t len);
2021-08-28 15:46:01 +08:00
```
Insert data buffer `buf`, `len` at offset `offset`. The iobuf is expanded
2022-08-01 19:53:25 +08:00
if required. The resulting `io->size` is always aligned to the `io->align` byte boundary; therefore,
2021-09-15 14:43:24 +08:00
to avoid memory fragmentation and frequent reallocations, set `align` to a higher value.
2021-09-15 20:37:57 +08:00
Parameters:
- `io` - iobuf to add data
- `offset` - Offset to add data
- `buf` - Data to add
2021-11-16 20:30:40 +08:00
- `len` - Data length
2021-09-15 20:37:57 +08:00
2021-11-16 20:30:40 +08:00
Return value: new `io` length
2021-09-15 20:37:57 +08:00
2021-09-15 14:43:24 +08:00
Usage example:
2021-08-25 14:59:31 +08:00
```c
2022-08-01 19:53:25 +08:00
struct mg_iobuf io; // Declare buffer
mg_iobuf_init(&io, 0, 16); // Initialise empty buffer with 16 byte alignment
2022-06-08 18:30:54 +08:00
```
<img src="images/mg_iobuf_add1.svg" alt="Function mg_iobuf_init()" />
```c
2022-08-01 19:53:25 +08:00
mg_iobuf_add(&io, io.len, "hello", 5); // Append "hello"
2021-08-28 15:46:01 +08:00
```
2022-06-08 18:30:54 +08:00
<img src="images/mg_iobuf_add2.svg" alt="Function mg_iobuf_add()" />
2021-09-15 14:43:24 +08:00
2021-08-28 15:46:01 +08:00
### mg\_iobuf\_del()
```c
size_t mg_iobuf_del(struct mg_iobuf *io, size_t offset, size_t len);
2021-08-25 14:59:31 +08:00
```
2021-08-28 15:46:01 +08:00
2021-09-15 14:43:24 +08:00
Delete `len` bytes starting from `offset`, and shift the remaining bytes.
If `len` is greater than `io->len`, nothing happens, so such call is silently ignored.
2021-09-15 20:37:57 +08:00
Parameters:
- `io` - iobuf to delete data
- `offset` - Start offset
- `len` - Amount of bytes to delete
2021-09-15 20:37:57 +08:00
2021-11-16 20:30:40 +08:00
Return value: New `io` length
2021-09-15 20:37:57 +08:00
2021-09-15 14:43:24 +08:00
Usage example:
```c
struct mg_iobuf io;
2022-08-06 02:55:15 +08:00
mg_iobuf_init(&io, 0, 16); // Empty buffer
mg_iobuf_add(&io, 0, "hi", 2); // io->len is 2, io->size is 16
mg_iobuf_del(&io, 0, "hi", 2); // io->len is 0, io->size is still 16
2021-09-15 14:43:24 +08:00
```
2022-08-06 02:44:55 +08:00
<img src="images/mg_iobuf_del.svg" alt="Function mg_iobuf_del()" />
2021-09-15 14:43:24 +08:00
## URL
### mg\_url\_port()
```c
unsigned short mg_url_port(const char *url);
```
2021-09-15 20:37:57 +08:00
Return port for given URL
Parameters:
- `url` - URL to extract port
2021-11-16 20:30:40 +08:00
Return value: Port for given URL or `0` if URL doesn't contain port and there
isn't default port for URL protocol
2021-09-15 14:43:24 +08:00
Usage example:
```c
unsigned short port1 = mg_url_port("htts://myhost.com") // port1 is now 443 (default https port)
unsigned short port2 = mg_url_port("127.0.0.1:567") // port2 is now 567
```
### mg\_url\_is_ssl()
```c
int mg_url_is_ssl(const char *url);
```
2021-09-15 20:37:57 +08:00
Check if given URL uses encrypted scheme
Parameters:
- `url` - URL to check
Return value: `0` is given URL uses encrypted scheme and non-zero otherwise
2021-09-15 14:43:24 +08:00
Usage example:
```c
if (mg_url_is_ssl("https://example.org") == 0) {
// scheme is encrypted
}
```
### mg\_url\_host()
```c
struct mg_str mg_url_host(const char *url);
```
Extract host name from given URL.
2021-09-15 20:37:57 +08:00
Parameters:
- `url` - a URL string
2021-09-15 20:37:57 +08:00
Return value: host name
2021-09-15 14:43:24 +08:00
Usage example:
```c
struct mg_str a = mg_url_host("https://my.example.org:1234"); // a == "my.example.org"
struct mg_str b = mg_url_host("tcp://[::1]"); // b == "[::1]"
2021-09-15 14:43:24 +08:00
```
### mg\_url\_user()
```c
struct mg_str mg_url_user(const char *url);
```
Extract user name from given URL.
2021-09-15 20:37:57 +08:00
Parameters:
- `url` - URL to extract user name
Return value: User name or empty string if not found
2021-09-15 20:37:57 +08:00
2021-09-15 14:43:24 +08:00
Usage example:
```c
struct mg_str user_name = mg_url_user("https://user@password@my.example.org"); // user_name is now "user"
```
### mg\_url\_pass()
```c
struct mg_str mg_url_pass(const char *url);
```
2021-09-15 20:37:57 +08:00
Extract password from given URL.
Parameters:
- `url` - URL to extract password
Return value: Password or empty string if not found
2021-09-15 14:43:24 +08:00
Usage example:
```c
struct mg_str pwd = mg_url_user("https://user@password@my.example.org"); // pwd is now "password"
```
### mg\_url\_uri()
```c
const char *mg_url_uri(const char *url);
```
2021-09-15 20:37:57 +08:00
Extract URI from given URL.
Note, that function returns pointer within `url`; there is no need to free() it explicitly
2021-09-15 14:43:24 +08:00
2021-09-15 20:37:57 +08:00
Parameters:
- `url` - URL to extract URI
Return value: URI or `\` if not found
2021-09-15 14:43:24 +08:00
Usage example:
```c
const char *uri = mg_url_uri("https://example.org/subdir/subsubdir"); // `uri` is now pointer to "subdir/subsubdir"
```
## Logging
Mongoose provides a set of functions and macros for logging. The application can
2021-09-15 14:43:24 +08:00
use these functions for its own purposes as well as the rest of Mongoose API.
### LOG()
```c
#define LOG(level, args)
#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
#define MG_INFO(args) MG_LOG(MG_LL_INFO, args)
#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
#define MG_VERBOSE(args) MG_LOG(MG_LL_VERBOSE, args)
2021-09-15 14:43:24 +08:00
```
Logging macros.
2021-09-15 14:43:24 +08:00
Usage example:
2021-09-15 14:43:24 +08:00
```c
MG_INFO(("Hello %s!", "world")); // Output "Hello, world"
2021-09-15 14:43:24 +08:00
```
### mg\_log\_set()
```c
void mg_log_set(const char *spec);
```
Set Mongoose logging level.
2021-09-15 20:37:57 +08:00
Parameters:
- `spec` - String, containing log level, can be one of the following values:
2022-05-25 18:14:42 +08:00
- `0` - Disable logging
- `1` - Log errors only
- `2` - Log errors and info messages
- `3` - Log errors, into and debug messages
- `4` - Log everything
2021-09-15 14:43:24 +08:00
Return value: None
2021-09-15 20:37:57 +08:00
2021-09-15 14:43:24 +08:00
It is possible to override log level per source file basis. For example, if
there is a file called `foo.c`, and you'd like to set a global level to `2`
(info) but increase log level for file foo.c to `debug`, then, a `spec` should
2021-09-15 14:43:24 +08:00
look like `"2,foo.c=3"`. There could be several comma-separated overrides.
Usage example:
```c
mg_log_set("2"); // Set log level to info
mg_log_set("2,foo.c=3,bar.c=0"); // Set log level to info, with overrides
```
### mg\_hexdump()
```c
void mg_hexdump(const void *buf, int len);
```
Log a hex dump of binary data `buf`, `len`.
Parameters:
- `buf` - Data pointer
- `len` - Data length
Return value: none
Usage example:
```c
mg_hexdump(c->recv.buf, c->recv.len); // Hex dump incoming data
```
2022-06-19 16:04:22 +08:00
### mg\_log\_set\_fn()
```c
2022-08-13 22:43:27 +08:00
void mg_log_set_fn(mg_pfn_t logfunc, void *param);
2022-06-19 16:04:22 +08:00
```
Redirect logs to a custom function. Parameters:
- `logfunc` - a pointer to a function that logs a single character
2022-08-13 22:43:27 +08:00
- `param` - a parameter for a logging function
2022-06-19 16:04:22 +08:00
Usage example: redirecting logs to syslog.
```c
2022-08-13 22:43:27 +08:00
static void mylog(char ch, void *param) {
2022-06-20 01:27:37 +08:00
static char buf[256];
static size_t len;
buf[len++] = ch;
if (ch == '\n' || len >= sizeof(buf)) {
syslog(LOG_INFO, "%.*s", (int) len, buf); // Send logs
len = 0;
2022-06-19 16:04:22 +08:00
}
}
...
2022-08-13 22:43:27 +08:00
mg_log_set_fn(mylog, NULL);
2022-06-19 16:04:22 +08:00
```
2021-09-15 14:43:24 +08:00
## Filesystem
2022-05-25 20:28:25 +08:00
### struct mg\_fs
2021-09-15 14:43:24 +08:00
2022-05-25 20:28:25 +08:00
```c
struct mg_fs {
int (*st)(const char *path, size_t *size, time_t *mtime); // stat file
void (*ls)(const char *path, void (*fn)(const char *, void *), void *);
void *(*op)(const char *path, int flags); // Open file
void (*cl)(void *fd); // Close file
size_t (*rd)(void *fd, void *buf, size_t len); // Read file
size_t (*wr)(void *fd, const void *buf, size_t len); // Write file
size_t (*sk)(void *fd, size_t offset); // Set file position
bool (*mv)(const char *from, const char *to); // Rename file
bool (*rm)(const char *path); // Delete file
bool (*mkd)(const char *path); // Create directory
};
enum { MG_FS_READ = 1, MG_FS_WRITE = 2, MG_FS_DIR = 4 };
```
Filesystem virtualisation layer.
Mongoose allows to override file IO operations in order to support different
2021-09-15 14:43:24 +08:00
storages, like programmable flash, no-filesystem devices etc.
In order to accomplish this, Mongoose provides a `struct mg_fs` API to
2022-05-25 03:36:21 +08:00
specify a custom filesystem. In addition to this, Mongoose provides several
2022-05-25 20:28:25 +08:00
built-in APIs - a standard POSIX, FatFS, and a "packed FS" API:
2021-09-15 14:43:24 +08:00
```c
2022-05-25 20:28:25 +08:00
extern struct mg_fs mg_fs_posix; // POSIX open/close/read/write/seek
2022-05-25 20:29:49 +08:00
extern struct mg_fs mg_fs_packed; // Packed FS, see examples/device-dashboard
2022-05-25 20:28:25 +08:00
extern struct mg_fs mg_fs_fat; // FAT FS
```
2021-09-15 14:43:24 +08:00
2022-05-25 20:28:25 +08:00
### struct mg\_fd
```c
struct mg_fd {
void *fd;
struct mg_fs *fs;
2021-09-15 14:43:24 +08:00
};
```
2022-05-25 20:28:25 +08:00
Opened file abstraction.
### mg\_fs\_open()
```c
struct mg_fd *mg_fs_open(struct mg_fs *fs, const char *path, int flags);
```
Open a file in a given filesystem.
Parameters:
- `fs` - a filesystem implementation
- `path` - a file path
- `flags` - desired flags, a combination of `MG_FS_READ` and `MG_FS_WRITE`
Return value: a non-NULL opened descriptor, or NULL on failure.
Usage example:
```c
struct mg_fd *fd = mg_fs_open(&mg_fs_posix, "/tmp/data.json", MG_FS_WRITE);
```
### mg\_fs\_close()
```c
void mg_fs_close(struct mg_fd *fd);
```
Close an opened file descriptor.
Parameters:
- `fd` - an opened file descriptor
Return value: none
### mg\_file\_read()
```c
char *mg_file_read(struct mg_fs *fs, const char *path, size_t *size);
```
Read the whole file in memory.
Parameters:
- `fs` - a filesystem implementation
- `path` - a file path
- `size` - if not NULL, will contained the size of the read file
Return value: on success, a pointer to file data, which is guaranteed
to the 0-terminated. On error, NULL.
Usage example:
```c
size_t size = 0;
char *data = mg_file_read(&mg_fs_packed, "/data.json", &size);
```
### mg\_file\_write()
```c
bool mg_file_write(struct mg_fs *fs, const char *path, const void *buf, size_t len);
```
Write a piece of data `buf`, `len` to a file `path`. If the file does not
exist, it gets created. The previous content, if any, is deleted.
Parameters:
- `fs` - a filesystem implementation
- `path` - a file path
- `buf` - a pointer to data to be written
- `len` - a data size
Return value: true on success, false on error
Usage example:
```c
mg_file_write(&mg_fs_fat, "/test.txt", "hi\n", 3);
```
### mg\_file\_printf()
```c
bool mg_file_printf(struct mg_fs *fs, const char *path, const char *fmt, ...);
```
Write a printf-formatted data to a file `path`. If the file does not
exist, it gets created. The previous content, if any, is deleted.
Parameters:
- `fs` - a filesystem implementation
- `path` - a file path
- `fmt` - a [mg_snprintf](#mg-snrpintf) format string
Return value: true on success, false on error
Usage example:
2021-09-15 14:43:24 +08:00
```c
2022-05-25 20:28:25 +08:00
mg_file_printf(&mg_fs_fat, "/test.txt", "%s\n", "hi");
2021-09-15 14:43:24 +08:00
```
### Packed filesystem
2022-05-25 03:36:21 +08:00
A packed filesystem allow to "pack" filesystem into a C file which then can
be compiled into the binary, forming a read-only file system.
This makes it possible to serve files on devices with no
filesystem. Even on devices with a filesystem, packing some files like Web UI
can be beneficial to be resilient to filesystem errors.
2022-05-25 02:13:58 +08:00
2021-09-15 14:43:24 +08:00
In order to use packed filesystem do the following:
2022-05-25 02:18:42 +08:00
1. Build **pack** tool from test/pack.c:
2022-05-25 02:13:58 +08:00
```sh
2022-05-25 02:18:42 +08:00
$ cc -o pack pack.c
2022-05-25 02:13:58 +08:00
```
2021-09-15 14:43:24 +08:00
2. Convert list of files into single .c:
2022-05-25 02:13:58 +08:00
```sh
$ ./pack index.html style.css > packed_fs.c
```
2021-09-15 14:43:24 +08:00
2022-05-25 02:13:58 +08:00
3. Build your app with `packed_fs.c`:
```sh
$ cc mongoose.c app.c packed_fs.c -DMG_ENABLE_PACKED_FS=1
```
2021-09-15 14:43:24 +08:00
2022-05-27 03:25:20 +08:00
<img src="images/packed.svg" alt="packed filesystem" />
2022-05-25 02:13:58 +08:00
4. In your application code:
2021-09-15 14:43:24 +08:00
```c
2022-05-25 02:13:58 +08:00
struct mg_http_serve_opts opts = {}; // Initialise empty options
opts.fs = &mg_fs_packed; // Use packed filesystem
2022-05-25 02:19:42 +08:00
opts.root_dir = "/"; // Set root directory
2022-05-25 02:13:58 +08:00
mg_http_serve_dir(c, hm, &opts); // Serve directory
2021-09-15 14:43:24 +08:00
```