From 94d2e86b60a8e4cef62e28930fec514c7f208a89 Mon Sep 17 00:00:00 2001 From: cpq Date: Tue, 8 Dec 2020 16:26:17 +0000 Subject: [PATCH] More docs --- docs/README.md | 883 ++++++++++++++++++++++++++++++++++++++++++++++++- mongoose.c | 4 +- mongoose.h | 1 - src/http.h | 1 - 4 files changed, 882 insertions(+), 7 deletions(-) diff --git a/docs/README.md b/docs/README.md index 146305cf..5aa12683 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,4 +1,4 @@ -# Overview +# User Guide ## Introduction @@ -209,6 +209,7 @@ $ cc my_app.c mongoose.c -D MG_MQTT_ENABLE=0 ``` Here is a list of build constants and their default values: + | Name | Default | Description | | ---- | ------- | ----------- | |`MG_ENABLE_LWIP` | 0 | Use LWIP low-level API instead of BSD sockets | @@ -226,7 +227,7 @@ Here is a list of build constants and their default values: |`MG_MAX_RECV_BUF_SIZE` | (3 * 1024 * 1024) | Maximum recv buffer size | |`MG_MAX_HTTP_HEADERS` | 40 | Maximum number of HTTP headers | -## Minimal example +## Minimal HTTP server This example is a simple static HTTP server that serves current directory: @@ -249,3 +250,881 @@ int main(int argc, char *argv[]) { return 0; } ``` + +## Minimal TCP echo server + +This example is a simple TCP echo server that listens on port 1234: + +```c +#include "mongoose.h" + +static const char *s_listening_address = "tcp://0.0.0.0:1234"; + +static void cb(struct mg_connection *c, int ev, void *ev_data, void *fn_data) { + if (ev == MG_EV_RECV) { + mg_send(c, c->recv.buf, c->recv.len); // Echo received data back + mg_iobuf_delete(&c->recv, c->recv.len); // And discard it + } +} + +int main(int argc, char *argv[]) { + struct mg_mgr mgr; + mg_mgr_init(&mgr); + mg_listen(&mgr, s_listening_address, cb, &mgr); + for (;;) mg_mgr_poll(&mgr, 1000); + mg_mgr_free(&mgr); + return 0; +} +``` + + +# API Reference + +## Core + +### struct mg_mgr + +```c +struct mg\_mgr { + struct mg_connection *conns; // List of active connections + struct mg_connection *dnsc; // DNS resolver connection + const char *dnsserver; // DNS server URL + int dnstimeout; // DNS resolve timeout in milliseconds +}; +``` +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 + struct mg_addr peer; // Remote peer address + void *fd; // Connected socket, or LWIP data + struct mg_iobuf recv; // Incoming data + struct mg_iobuf send; // Outgoing data + mg_event_handler_t fn; // User-specified event handler function + void *fn_data; // User-speficied function parameter + mg_event_handler_t pfn; // Protocol-specific handler function + void *pfn_data; // Protocol-specific function parameter + char label[32]; // Arbitrary label + 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 + 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_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, +or an outbout connection. + +### mg\_mgr_init() + +```c +void mg_mgr_init(struct mg_mgr *); +``` + +Initialise event manager structure: set a list of active connections to NULL, +set DNS server and timeout to their default values, etc. + + +### mg\_mgr_poll() + +```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 it is, read it into the `c->recv` buffer, send `MG_EV_RECV` event +- 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 + +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 user-specific handler. It parses +incoming data and may invoke protocol-specific events like `MG_EV_HTTP_MSG`. + + +### mh\_mgr\_free() + +```c +void mg_mgr_free(struct mg_mgr *mgr); +``` + +Close all connections, and free all resources. + + +### 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`. +- `url` - specifies local IP address and port to listen on, e.g. + `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. + +### mg\_connect() + +```c +struct mg_connection *mg_connect(struct mg_mgr *mgr, const char *url, + mg_event_handler_t fn, void *fn_data); +``` + +Create an outbout connection, append this connection to `mgr->conns`. +- `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 + 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. + + +### 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 +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. + + +### mg\_printf() + +```c +int mg_printf(struct mg_connection *, const char *fmt, ...); + +``` + +Same as `mg_send()`, but formats data using `printf()` semantics. Return +number of bytes appended to the output buffer. + + +### mg\_vprintf() + +```c +int mg_vprintf(struct mg_connection *, const char *fmt, va_list ap); +``` + +Same as `mg_printf()`, but takes `va_list` argument as a parameter. + + +### mg\_socketpair() + +```c +bool mg_socketpair(int *blocking, int *non_blocking); +``` + +Create a socket pair for exchanging data in multi-threaded environment. The +`blocking` socket is blocking - it should be passed to the processing task. +The `non_blocking` socket is non blocking, it should be used by an event +handler function. Return value: true on success, false on error. + + +## IO buffers + +### struct mg\_iobuf + +```c +struct mg_iobuf { + unsigned char *buf; + size_t size, len; +}; +``` + +Generic IO buffer. The `size` specifies an allocation size of the data pointed +by `buf`, and `len` specifies number of bytes currently stored. + +### mg\_iobuf\_init() + +```c +void mg_iobuf_init(struct mg_iobuf *io, size_t size); +``` + +Initialise IO buffer, allocate `size` bytes. + + +### mg\_iobuf\_resize() + +```c +void mg_iobuf_resize(struct mg_iobuf *io, size_t size); +``` + +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. + + +### mg\_iobuf\_free() + +```c +void mg_iobuf_free(struct mg_iobuf *io); +``` + +Free memory pointed by `io->buf` and set to NULL. Both `size` and `len` are set +to 0. + + +### mg\_iobuf\_append() + +```c +size_t mg_iobuf_append(struct mg_iobuf *io, const void *data, size_t data_size, size_t granularity); +``` + +Append `data` bytes of size `data_size` to the end of the buffer. The buffer +is expanded if `data_size` is greater than `io->size - io->len`. If that +happens, the `io->buf` can change. The resulting `io->size` is always +set to the `granularity` byte boundary. Example: + +```c +struct mg_iobuf io; +mg_iobuf_init(&io, 0); // Empty buffer +mg_iobuf_append(&io, "hi", 2, 1024); // io->len is 2, io->size is 1024 +``` + +### mg\_iobuf\_delete() + +```c +size_t mg_iobuf_delete(struct mg_iobuf *io, size_t len); +``` + +Discard `len` bytes from the beginning of the buffer, and shift the remaining +bytes to the beginning. If `len` is greater than `io->len`, nothing happens, +so such call is silently ignored. + + +## HTTP + +### struct mg\_http\_header + +```c +struct mg_http_header { + struct mg_str name; + struct mg_str value; +}; +``` + +### struct mg\_http\_message + +```c +struct mg_http_message { + // GET /foo/bar/baz?aa=b&cc=ddd HTTP/1.1 + // method |-| |----uri---| |--query--| |proto-| + + struct mg_str method, uri, query, proto; // Request/response line + struct mg_http_header headers[MG_MAX_HTTP_HEADERS]; // Headers + struct mg_str body; // Body + struct mg_str message; // Request line + headers + body +}; +``` + +### mg\_http\_listen() + +```c +struct mg_connection *mg_http_listen(struct mg_mgr *, const char *url, + mg_event_handler_t fn, void *fn_data); +``` + +Create HTTP listener. + +- `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 + event handler is called. This pointer is also stored in a connection + structure as `c->fn_data` + + +### 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. +- `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 + event handler is called. This pointer is also stored in a connection + structure as `c->fn_data` + + + + +### mg\_http\_get\_request\_len() + +```c +int mg_http_get_request_len(const unsigned char *buf, size_t buf_len); +``` + +Return value: -1 on error, +0 if a message is incomplete, or the length of request. The length of +request is a number of bytes till the end of HTTP headers. It does not include +length of HTTP body. + + +### mg\_http\_parse() + +```c +int mg_http_parse(const char *s, size_t len, struct mg_http_message *hm); +``` + +Parse string `s`, `len` into a structure `hm`. Return request length - see +`mg_http_get_request_len()`. + + +### mg\_http\_printf\_chunk() + +``` +void mg_http_printf_chunk(struct mg_connection *cnn, const char *fmt, ...); +``` + +Write a chunk of data in chunked encoding format, using `printf()` semantic. + + +### 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. + + +### mg\_serve\_dir() + +```c +void mg_http_serve_dir(struct mg_connection *, struct mg_http_message *hm, + const char *path); +``` + +Serve static files using `path` as a root directory. + + +### mg\_serve\_file() + +```c +void mg_http_serve_file(struct mg_connection *, struct mg_http_message *hm, + const char *path, const char *mimetype); +``` + +Serve static file. + + +### mg\_http\_reply() + +```c +void mg_http_reply(struct mg_connection *c, int code, const char *fmt, ...); +``` + +Send simple HTTP response using `printf()` semantic. +`code` is HTTP response code, `fmt` is format for the HTTP body. + + +### mg\_http\_header() + +```c +struct mg_str *mg_http_get_header(struct mg_http_message *, const char *name); +``` + +Return value of HTTP header, or NULL if not found. + +### mg\_http\_get\_var() + +```c +int mg_http_get_var(const struct mg_str *, const char *name, char *buf, int len); +``` + +Decode HTTP variable `name` into a given buffer. Return length of decoded +variable. Zero or negative value means error. + +### mg\_url\_decode() + +```c +int mg_url_decode(const char *s, size_t n, char *to, size_t to_len, int form); +``` + + +URL-decode string `s`, `n` unto a buffer `buf`, `len`. Return decoded length. +If `form` is non-zero, then `+` is decoded as whitespace. + + +### mg\_http\_creds() + +```c +void mg_http_creds(struct mg_http_message *, char *user, int userlen, char *pass, int passlen); +``` + +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. + + +### mg\_http\_match\_uri() + +```c +bool mg_http_match_uri(const struct mg_http_message *, const char *glob); +``` + +Return true if HTTP request matches a given glob pattern; false otherwise. + +### mg\_http\_upload() + +```c +int mg_http_upload(struct mg_connection *, struct mg_http_message *hm, + const char *dir); +``` + +Handle file upload. See file upload example. + + +### mg\_http\_bauth() + +```c +void mg_http_bauth(struct mg_connection *, const char *user, const char *pass); +``` + +Write a Basic `Authorization` header to the output buffer. + + +## Websocket + +### struct mg\_ws\_message + +```c +struct mg_ws_message { + struct mg_str data; + uint8_t flags; // Websocket message flags +}; +``` + +### mg\_ws\_connect() + +```c +struct mg_connection *mg_ws_connect(struct mg_mgr *, const char *url, + mg_event_handler_t fn, void *fn_data, + const char *fmt, ...); +``` + +Create client Websocket connection. +- `url` - specifies remote URL, e.g. `http://google.com` +- `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 + 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 + + +### mg\_ws\_upgrade() + +```c +void mg_ws_upgrade(struct mg_connection *, struct mg_http_message *); +``` + +Upgrade given HTTP connection to Websocket. + + +### mg\_ws\_send() + +```c +size_t mg_ws_send(struct mg_connection *, const char *buf, size_t len, int op); +``` + +Send `buf`, `len` to the websocket peer. `op` is the Websocket message type: + +```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 +``` + +## MQTT + +### struct mg\_mqtt\_opts + +```c +struct mg_mqtt_opts { + struct mg_str client_id; + struct mg_str will_topic; + struct mg_str will_message; + uint8_t qos; // Quality of service + bool will_retain; // Retain last will + bool clean; // Use clean session, 0 or 1 + uint16_t keepalive; // Keep-alive timer in seconds +}; +``` + +### struct mg\_mqtt\_message + +```c +struct mg_mqtt_message { + struct mg_str topic; + struct mg_str data; +}; +``` + + +### mg\_mqtt\_connect() + +```c +struct mg_connection *mg_mqtt_connect(struct mg_mgr *, const char *url, + struct mg_mqtt_opts *opts, + mg_event_handler_t fn, void *fn_data); +``` + +Create client MQTT connection. +- `url` - specifies remote URL, e.g. `http://google.com` +- `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 + event handler is called. This pointer is also stored in a connection + structure as `c->fn_data` + + +### mg\_mqtt\_pub() + +```c +void mg_mqtt_pub(struct mg_connection *, struct mg_str *topic, + struct mg_str *data); +``` + +Publish message `data` to the topic `topic`. + + +### mg\_mqtt\_sub() + +```c +void mg_mqtt_sub(struct mg_connection *, struct mg_str *topic); +``` + +Subscribe to topic `topic`. + + +## TLS + +### struct mg\_tls\_opts + +```c +struct mg_tls_opts { + const char *ca; // CA certificate file. For both listeners and clients + const char *cert; // Certificate + const char *certkey; // Certificate key + const char *ciphers; // Cipher list + const char *srvname; // If not NULL, enables server name verification +}; +``` + +Describes TLS parameters + + +### mg\_tls\_init() + +```c +int mg_tls_init(struct mg_connection *c, struct mg_tls_opts *opts); +``` + +Turns on TLS on a given connection. + + +## Timers + + +### struct mg\_timer + +```c +struct mg_timer { + int period_ms; // Timer period in milliseconds + int flags; // Possible flags values below +#define MG_TIMER_REPEAT 1 // Call function periodically, otherwise run once +#define MG_TIMER_RUN_NOW 2 // Call immediately when timer is set + void (*fn)(void *); // Function to call + void *arg; // Function agrument + unsigned long expire; // Expiration timestamp in milliseconds + struct mg_timer *next; // Linkage in g_timers list +}; +``` + +Timer structure. + +### mg\_timer\_init() + +```c +void mg_timer_init(struct mg_timer *, int ms, int flags, void (*fn)(void *), void *fn_data); +``` + +Setup a timer. +- `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 + +A timer gets initialised and linked into the `g_timers` list: + +```c +struct mg_timer *g_timers; +``` + +### mg\_timer\_free() + +```c +void mg_timer_free(struct mg_timer *); +``` + +Free timer, remove it from the `g_timers` list. + +### mg\_timer\_poll() + +```c +void mg_timer_poll(unsigned long uptime_ms); +``` + +Traverse list of timers, and call them if current timestamp `uptime_ms` is +past the timer's expiration time. + +## Utility functions + + +### mg\_file\_read() + +```c +char *mg_file_read(const char *path); +``` + +Read file contents into a nul-terminated malloc-ed string. It is a caller's +responsibility to free() a returned pointer. + +### mg\_file\_size() + +```c +size_t mg_file_size(const char *path); +``` + +Return file size, or 0 on failure. Empty files also report 0 length. + + +### mg\_file\_write() + +```c +int mg_file_write(const char *path, const char *fmt, ...); +``` + +Write into a file `path` using `printf()` semantics. Return number of bytes written. + + +### mg\_random() + +```c +void mg_random(void *buf, size_t len); +``` + +Fill in buffer `buf`, `len` with random data. + + +### mg\_globmatch() + +```c +bool mg_globmatch(const char *pattern, int plen, const char *s, int n); +``` + +Return true if string `s`, `n` matches glob pattern `pattern`, `plen`. +The glob pattern matching rules are as follows: + +- `?` matches any single character +- `*` matches zero or more characters except `/` +- `#` matches zero or more characters +- any other caracter matches itself + + +### mg\_next\_comma\_entry() + +```c +bool mg_next_comma_entry(struct mg_str *s, struct mg_str *k, struct mg_str *v); +``` + +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. + +IMPORTANT: this function modifies `s` by pointing to the next entry. Usage +example: + +```c +struct mg_str k, v, s = mg_str("a=333,b=777"); +while (mg_next_comma_entry(&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] +``` + +### mg\_ntohs() + +```c +uint16_t mg_ntohs(uint16_t net); +``` + +Convert `uint16_t` value to host order. + + +### mg\_ntohl() + +```c +uint32_t mg_ntohl(uint32_t net); +``` + +Convert `uint32_t` value to host order. + + +### mg\_hexdump() + +```c +char *mg_hexdump(const void *buf, int len); +``` + +Hexdump binary data `buf`, `len` into malloc-ed buffer and return it. +It is a caller's responsibility to free() returned pointer. + +### mg\_hex() + +```c +char *mg_hex(const void *buf, int 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. +Return value: `dst` pointer. The encoded characters are lowecase, +for example `mg_hex("hi", 2, buf)` outputs `6869` and 0 byte, 5 bytes overall. + + +### mg\_unhex() + +```c +void mg_unhex(const char *buf, int len, unsigned char *to); +``` + +Hex-decode string `buf`, `len` into a buffer `to`. The `to` buffer should be +at least `lsn` / 2 big. + + +### mg\_unhexn() + +```c +unsigned long mg_unhexn(const char *s, int len); +``` + +Parse `len` characters of the hex-encoded string `s`, return parsed value. +The maximum value of `len` is the width of the `long` x 2, for example +on 32-bit platforms it is 8. + + +### mg\_asprintf() + +```c +int mg_asprintf(char **buf, size_t size, const char *fmt, ...); +``` + +Print message specified by printf-like format string `fmt` into a buffer +pointed by `buf` of size `size`. If `size` is large enough to hold the whole +message, then a message is stored in `*buf`. If it does not fit, then +a large enough buffer is allocated to hold a message, and `buf` is changed to +point to that buffer. Return value: number of bytes printed. + + +### mg\_vasprintf() + +```c +int mg_vasprintf(char **buf, size_t size, const char *fmt, va_list ap); +``` + +Same as `mg_asprintf()` but uses `va_list` argument. + + +### mg\_to64() + +``` +int64_t mg_to64(const char *s); +``` + +Parse 64-bit integer value held by string `s`. + +### mg\_aton() + +``` +bool mg_aton(const char *s, uint32_t *ipaddr); +``` + +Parse IP address held by `s` and store it in `ipaddr`. Return true on success. + + +### mg\_ntoa() + +```c +char *mg_ntoa(uint32_t ipaddr, char *buf, size_t len); +``` + +Stringify IP address `ipaddr` into a buffer `buf`, `len`. Return `buf`. + +### mg\_time() + +``` +double mg_time(void); +``` + +Return current time as UNIX epoch, using `double` value for sub-second accuracy. + + +### mg\_millis() + +```c +unsigned long mg_millis(void); +``` + +Return current uptime in milliseconds. + + +### mg\_usleep() + +```c +void mg_usleep(unsigned long usecs); +``` + +Block for a given number of microseconds. diff --git a/mongoose.c b/mongoose.c index 1cdafb10..10576ac0 100644 --- a/mongoose.c +++ b/mongoose.c @@ -1051,9 +1051,7 @@ struct mg_connection *mg_http_listen(struct mg_mgr *mgr, const char *url, void mg_iobuf_resize(struct mg_iobuf *io, size_t new_size) { if (new_size == 0) { - free(io->buf); - io->buf = NULL; - io->len = io->size = 0; + mg_iobuf_free(io); } else if (new_size != io->size) { // NOTE(lsm): do not use realloc here. Use malloc/free only, to ease the // porting to some obscure platforms like FreeRTOS diff --git a/mongoose.h b/mongoose.h index 0a829230..2ba1ef48 100644 --- a/mongoose.h +++ b/mongoose.h @@ -680,7 +680,6 @@ void mg_http_reply(struct mg_connection *c, int code, const char *fmt, ...); struct mg_str *mg_http_get_header(struct mg_http_message *, const char *name); void mg_http_event_handler(struct mg_connection *c, int ev); int mg_http_get_var(const struct mg_str *, const char *name, char *, int); -int mg_http_unescape(const char *s, int n, char *buf, size_t len); int mg_url_decode(const char *s, size_t n, char *to, size_t to_len, int form); void mg_http_creds(struct mg_http_message *, char *user, int, char *pass, int); bool mg_http_match_uri(const struct mg_http_message *, const char *glob); diff --git a/src/http.h b/src/http.h index 35a55531..225e57b4 100644 --- a/src/http.h +++ b/src/http.h @@ -36,7 +36,6 @@ void mg_http_reply(struct mg_connection *c, int code, const char *fmt, ...); struct mg_str *mg_http_get_header(struct mg_http_message *, const char *name); void mg_http_event_handler(struct mg_connection *c, int ev); int mg_http_get_var(const struct mg_str *, const char *name, char *, int); -int mg_http_unescape(const char *s, int n, char *buf, size_t len); int mg_url_decode(const char *s, size_t n, char *to, size_t to_len, int form); void mg_http_creds(struct mg_http_message *, char *user, int, char *pass, int); bool mg_http_match_uri(const struct mg_http_message *, const char *glob);