Commit 34eb3f1e authored by Sergey Lyubka's avatar Sergey Lyubka Committed by GitHub

Merge pull request #855 from cesanta/dev

Mongoose 6.8
parents 7c049307 9d30e892
......@@ -8,7 +8,7 @@ used by vast number of open source and
commercial products - it even runs on the International Space station!
Mongoose makes embedded network programming fast, robust, and easy.
- [Download Mongoose Source Code here](https://www.cesanta.com)
- [Download Mongoose Source Code here](https://www.cesanta.com/download.html)
Looking for a complete IoT firmware solution?
......@@ -17,9 +17,9 @@ Check out [Mongoose OS](https://mongoose-os.com) - open source embedded operatin
# Support
- [Study mongoose example code](https://github.com/cesanta/mongoose/tree/master/examples)
- [Read User Guide and API reference](https://docs.cesanta.com/mongoose)
- [Support Forum - ask your technical questions here] (http://forum.cesanta.com/index.php?p=/categories/mongoose)
- [Commercial licensing and support available] (https://www.cesanta.com/services-support)
- [Check our latest releases] (https://github.com/cesanta/mongoose/releases)
- [Support Forum - ask your technical questions here](https://forum.mongoose-os.com/categories/mongoose)
- [Commercial licensing and support available](https://www.cesanta.com/licensing.html)
- [Check our latest releases](https://github.com/cesanta/mongoose/releases)
# Features
......@@ -47,7 +47,7 @@ Check out [Mongoose OS](https://mongoose-os.com) - open source embedded operatin
Mongoose is released under Commercial and [GNU GPL v.2](http://www.gnu.org/licenses/old-licenses/gpl-2.0.html) open source licenses.
Commercial Projects: [Contact us for commercial license.] (https://www.cesanta.com/contact)
Commercial Projects: [Contact us for commercial license.](https://www.cesanta.com/contact.html)
# Dashboard Example
......@@ -55,18 +55,14 @@ Mongoose is often used to implement device dashboards and real-time
data exchange over Websocket. Here is a dashboard example that illustrates
the functionality:
![](http://www.cesanta.com/hubfs/www.cesanta.com/diagrams/dash_mongoose_diagram.png)
![](http://www.cesanta.com/images/dashboard.png)
[Developing a new product? Contact us today to discuss how Mongoose can help.
](https://www.cesanta.com/contact)
[Developing a new product? Contact us today to discuss how Mongoose can help.](https://www.cesanta.com/contact.html)
# Contributions
To submit contributions, sign
[Cesanta CLA](https://docs.cesanta.com/contributors_la.shtml)
To submit contributions, sign [Cesanta CLA](https://cesanta.com/cla.html)
and send GitHub pull request. You retain the copyright on your contributions.
# Looking for a pre-compiled Mongoose web server Windows or Mac binary?
- [Download pre-compiled Mongoose web server binary.](https://www.cesanta.com/products/binary)
[![Analytics](https://ga-beacon.appspot.com/UA-42732794-5/project-page)](https://github.com/cesanta/mongoose)
- [Download pre-compiled Mongoose web server binary.](https://www.cesanta.com/binary.html)
......@@ -7,5 +7,5 @@ signature: |
---
Frees the memory allocated for options.
If the cm paramater doesn't contain any option it does nothing.
If the cm parameter doesn't contain any option it does nothing.
......@@ -21,5 +21,5 @@ This function doesn't update the `name` and `rdata` pointers in the `rr`
struct because they might be invalidated as soon as the IO buffer grows
again.
Returns the number of bytes appened or -1 in case of error.
Returns the number of bytes appended or -1 in case of error.
......@@ -11,6 +11,7 @@ items:
- { name: mg_send_websocket_handshake.md }
- { name: mg_send_websocket_handshake2.md }
- { name: mg_send_websocket_handshake3.md }
- { name: mg_send_websocket_handshake3v.md }
- { name: mg_set_protocol_http_websocket.md }
- { name: mg_url_decode.md }
- { name: struct_http_message.md }
......
......@@ -4,9 +4,8 @@ decl_name: "mg_connect_ws"
symbol_kind: "func"
signature: |
struct mg_connection *mg_connect_ws(struct mg_mgr *mgr,
mg_event_handler_t event_handler,
const char *url, const char *protocol,
const char *extra_headers);
MG_CB(mg_event_handler_t event_handler,
void *user_data);
---
Helper function that creates an outbound WebSocket connection.
......
......@@ -3,11 +3,8 @@ title: "mg_connect_ws_opt()"
decl_name: "mg_connect_ws_opt"
symbol_kind: "func"
signature: |
struct mg_connection *mg_connect_ws_opt(struct mg_mgr *mgr,
mg_event_handler_t ev_handler,
struct mg_connect_opts opts,
const char *url, const char *protocol,
const char *extra_headers);
struct mg_connection *mg_connect_ws_opt(
struct mg_mgr *mgr, MG_CB(mg_event_handler_t ev_handler, void *user_data);
---
Helper function that creates an outbound WebSocket connection
......
......@@ -9,5 +9,6 @@ signature: |
Sends multiple websocket frames.
Like `mg_send_websocket_frame()`, but composes a frame from multiple buffers.
Like `mg_send_websocket_frame()`, but composes a frame from multiple
*buffers.
---
title: "mg_send_websocket_handshake3v()"
decl_name: "mg_send_websocket_handshake3v"
symbol_kind: "func"
signature: |
void mg_send_websocket_handshake3v(struct mg_connection *nc,
const struct mg_str path,
const struct mg_str host,
const struct mg_str protocol,
const struct mg_str extra_headers,
const struct mg_str user,
const struct mg_str pass);
---
Same as mg_send_websocket_handshake3 but with strings not necessarily
NUL-temrinated
......@@ -13,6 +13,7 @@ Source string is specified by (`src`, `src_len`), and destination is
(`dst`, `dst_len`). If `is_form_url_encoded` is non-zero, then
`+` character is decoded as a blank space character. This function
guarantees to NUL-terminate the destination. If destination is too small,
then the source string is partially decoded and `-1` is returned. Otherwise,
then the source string is partially decoded and `-1` is returned.
*Otherwise,
a length of the decoded string is returned, not counting final NUL.
......@@ -5,6 +5,7 @@ symbol_kind: "struct"
signature: |
struct http_message {
struct mg_str message; /* Whole message: request line + headers + body */
struct mg_str body; /* Message body. 0-length for requests with no body */
/* HTTP Request line (or HTTP response line) */
struct mg_str method; /* "GET" */
......@@ -28,9 +29,6 @@ signature: |
/* Headers */
struct mg_str header_names[MG_MAX_HTTP_HEADERS];
struct mg_str header_values[MG_MAX_HTTP_HEADERS];
/* Message body */
struct mg_str body; /* Zero-length for requests with no body */
};
---
......
......@@ -3,11 +3,9 @@ title: "mg_connect_http()"
decl_name: "mg_connect_http"
symbol_kind: "func"
signature: |
struct mg_connection *mg_connect_http(struct mg_mgr *mgr,
mg_event_handler_t event_handler,
const char *url,
const char *extra_headers,
const char *post_data);
struct mg_connection *mg_connect_http(
struct mg_mgr *mgr,
MG_CB(mg_event_handler_t event_handler, void *user_data);
---
Helper function that creates an outbound HTTP connection.
......
......@@ -3,12 +3,8 @@ title: "mg_connect_http_opt()"
decl_name: "mg_connect_http_opt"
symbol_kind: "func"
signature: |
struct mg_connection *mg_connect_http_opt(struct mg_mgr *mgr,
mg_event_handler_t ev_handler,
struct mg_connect_opts opts,
const char *url,
const char *extra_headers,
const char *post_data);
struct mg_connection *mg_connect_http_opt(
struct mg_mgr *mgr, MG_CB(mg_event_handler_t ev_handler, void *user_data);
---
Helper function that creates an outbound HTTP connection.
......
......@@ -3,6 +3,7 @@ title: "Server API reference"
symbol_kind: "intro"
decl_name: "http_server.h"
items:
- { name: mg_check_digest_auth.md }
- { name: mg_file_upload_handler.md }
- { name: mg_get_http_basic_auth.md }
- { name: mg_get_http_header.md }
......
---
title: "mg_check_digest_auth()"
decl_name: "mg_check_digest_auth"
symbol_kind: "func"
signature: |
int mg_check_digest_auth(struct mg_str method, struct mg_str uri,
struct mg_str username, struct mg_str cnonce,
struct mg_str response, struct mg_str qop,
struct mg_str nc, struct mg_str nonce,
struct mg_str auth_domain, FILE *fp);
---
Authenticates given response params against an opened password file.
Returns 1 if authenticated, 0 otherwise.
It's used by mg_http_check_digest_auth().
......@@ -4,7 +4,8 @@ decl_name: "mg_file_upload_handler"
symbol_kind: "func"
signature: |
void mg_file_upload_handler(struct mg_connection *nc, int ev, void *ev_data,
mg_fu_fname_fn local_name_fn);
mg_fu_fname_fn local_name_fn
MG_UD_ARG(void *user_data);
---
File upload handler.
......
......@@ -12,5 +12,6 @@ Fetches a HTTP form variable.
Fetches a variable `name` from a `buf` into a buffer specified by `dst`,
`dst_len`. The destination is always zero-terminated. Returns the length of
a fetched variable. If not found, 0 is returned. `buf` must be valid
url-encoded buffer. If destination is too small, `-1` is returned.
url-encoded buffer. If destination is too small or an error occured,
negative number is returned.
......@@ -12,7 +12,7 @@ Sends a redirect response.
`status_code` should be either 301 or 302 and `location` point to the
new location.
If `extra_headers` is not empty, then `extra_headers` are also sent
after the reponse line. `extra_headers` must NOT end end with new line.
after the response line. `extra_headers` must NOT end end with new line.
Example:
......
......@@ -4,7 +4,8 @@ decl_name: "mg_register_http_endpoint"
symbol_kind: "func"
signature: |
void mg_register_http_endpoint(struct mg_connection *nc, const char *uri_path,
mg_event_handler_t handler);
MG_CB(mg_event_handler_t handler,
void *user_data);
---
Registers a callback for a specified http endpoint
......@@ -20,7 +21,7 @@ static void handle_hello1(struct mg_connection *nc, int ev, void *ev_data) {
nc->flags |= MG_F_SEND_AND_CLOSE;
}
static void handle_hello1(struct mg_connection *nc, int ev, void *ev_data) {
static void handle_hello2(struct mg_connection *nc, int ev, void *ev_data) {
(void) ev; (void) ev_data;
mg_printf(nc, "HTTP/1.0 200 OK\r\n\r\n[I am Hello2]");
nc->flags |= MG_F_SEND_AND_CLOSE;
......
......@@ -9,7 +9,7 @@ signature: |
Sends buffer `buf` of size `len` to the client using chunked HTTP encoding.
This function sends the buffer size as hex number + newline first, then
the buffer itself, then the newline. For example,
`mg_send_http_chunk(nc, "foo", 3)` whill append the `3\r\nfoo\r\n` string
`mg_send_http_chunk(nc, "foo", 3)` will append the `3\r\nfoo\r\n` string
to the `nc->send_mbuf` output IO buffer.
NOTE: The HTTP header "Transfer-Encoding: chunked" should be sent prior to
......
......@@ -9,7 +9,7 @@ signature: |
Sends the response status line.
If `extra_headers` is not NULL, then `extra_headers` are also sent
after the reponse line. `extra_headers` must NOT end end with new line.
after the response line. `extra_headers` must NOT end end with new line.
Example:
mg_send_response_line(nc, 200, "Access-Control-Allow-Origin: *");
......
......@@ -5,6 +5,7 @@ decl_name: "mqtt.h"
items:
- { name: mg_mqtt_connack.md }
- { name: mg_mqtt_disconnect.md }
- { name: mg_mqtt_match_topic_expression.md }
- { name: mg_mqtt_next_subscribe_topic.md }
- { name: mg_mqtt_ping.md }
- { name: mg_mqtt_pong.md }
......@@ -17,6 +18,7 @@ items:
- { name: mg_mqtt_subscribe.md }
- { name: mg_mqtt_unsuback.md }
- { name: mg_mqtt_unsubscribe.md }
- { name: mg_mqtt_vmatch_topic_expression.md }
- { name: mg_send_mqtt_handshake.md }
- { name: mg_send_mqtt_handshake_opt.md }
- { name: mg_set_protocol_mqtt.md }
......
---
title: "mg_mqtt_match_topic_expression()"
decl_name: "mg_mqtt_match_topic_expression"
symbol_kind: "func"
signature: |
int mg_mqtt_match_topic_expression(struct mg_str exp, struct mg_str topic);
---
Matches a topic against a topic expression
Returns 1 if it matches; 0 otherwise.
---
title: "mg_mqtt_vmatch_topic_expression()"
decl_name: "mg_mqtt_vmatch_topic_expression"
symbol_kind: "func"
signature: |
int mg_mqtt_vmatch_topic_expression(const char *exp, struct mg_str topic);
---
Same as `mg_mqtt_match_topic_expression()`, but takes `exp` as a
NULL-terminated string.
......@@ -5,6 +5,7 @@ symbol_kind: "struct"
signature: |
struct mg_mqtt_proto_data {
uint16_t keep_alive;
double last_control_time;
};
---
......
......@@ -11,7 +11,6 @@ items:
- { name: mg_check_ip_acl.md }
- { name: mg_connect.md }
- { name: mg_connect_opt.md }
- { name: mg_enable_javascript.md }
- { name: mg_mgr_free.md }
- { name: mg_mgr_init.md }
- { name: mg_mgr_init_opt.md }
......
......@@ -3,7 +3,9 @@ title: "mg_add_sock()"
decl_name: "mg_add_sock"
symbol_kind: "func"
signature: |
struct mg_connection *mg_add_sock(struct mg_mgr *, sock_t, mg_event_handler_t);
struct mg_connection *mg_add_sock(struct mg_mgr *mgr, sock_t sock,
MG_CB(mg_event_handler_t handler,
void *user_data);
---
Creates a connection, associates it with the given socket and event handler
......
......@@ -3,9 +3,9 @@ title: "mg_add_sock_opt()"
decl_name: "mg_add_sock_opt"
symbol_kind: "func"
signature: |
struct mg_connection *mg_add_sock_opt(struct mg_mgr *, sock_t,
mg_event_handler_t,
struct mg_add_sock_opts);
struct mg_connection *mg_add_sock_opt(struct mg_mgr *mgr, sock_t sock,
MG_CB(mg_event_handler_t handler,
void *user_data);
---
Creates a connection, associates it with the given socket and event handler
......
......@@ -3,8 +3,9 @@ title: "mg_bind()"
decl_name: "mg_bind"
symbol_kind: "func"
signature: |
struct mg_connection *mg_bind(struct mg_mgr *, const char *,
mg_event_handler_t);
struct mg_connection *mg_bind(struct mg_mgr *mgr, const char *address,
MG_CB(mg_event_handler_t handler,
void *user_data);
---
Creates a listening connection.
......
......@@ -4,8 +4,8 @@ decl_name: "mg_bind_opt"
symbol_kind: "func"
signature: |
struct mg_connection *mg_bind_opt(struct mg_mgr *mgr, const char *address,
mg_event_handler_t handler,
struct mg_bind_opts opts);
MG_CB(mg_event_handler_t handler,
void *user_data);
---
Creates a listening connection.
......@@ -15,7 +15,7 @@ the same as for the `mg_connect()` call, where `HOST` part is optional.
`address` can be just a port number, e.g. `:8000`. To bind to a specific
interface, an IP address can be specified, e.g. `1.2.3.4:8000`. By default,
a TCP connection is created. To create UDP connection, prepend `udp://`
prefix, e.g. `udp://:8000`. To summarize, `address` paramer has following
prefix, e.g. `udp://:8000`. To summarize, `address` parameter has following
format: `[PROTO://][IP_ADDRESS]:PORT`, where `PROTO` could be `tcp` or
`udp`.
......
......@@ -3,7 +3,8 @@ title: "mg_broadcast()"
decl_name: "mg_broadcast"
symbol_kind: "func"
signature: |
void mg_broadcast(struct mg_mgr *, mg_event_handler_t func, void *, size_t);
void mg_broadcast(struct mg_mgr *mgr, mg_event_handler_t cb, void *data,
size_t len);
---
Passes a message of a given length to all connections.
......
......@@ -18,7 +18,7 @@ Subnet masks may vary from 0 to 32, inclusive. The default setting
is to allow all access. On each request the full list is traversed,
and the last match wins. Example:
`-0.0.0.0/0,+192.168/16` - deny all acccesses, only allow 192.168/16 subnet
`-0.0.0.0/0,+192.168/16` - deny all accesses, only allow 192.168/16 subnet
To learn more about subnet masks, see this
link:https://en.wikipedia.org/wiki/Subnetwork[Wikipedia page on Subnetwork].
......
......@@ -4,7 +4,8 @@ decl_name: "mg_connect"
symbol_kind: "func"
signature: |
struct mg_connection *mg_connect(struct mg_mgr *mgr, const char *address,
mg_event_handler_t handler);
MG_CB(mg_event_handler_t handler,
void *user_data);
---
Connects to a remote host.
......
......@@ -4,8 +4,8 @@ decl_name: "mg_connect_opt"
symbol_kind: "func"
signature: |
struct mg_connection *mg_connect_opt(struct mg_mgr *mgr, const char *address,
mg_event_handler_t handler,
struct mg_connect_opts opts);
MG_CB(mg_event_handler_t handler,
void *user_data);
---
Connects to a remote host.
......
---
title: "mg_enable_javascript()"
decl_name: "mg_enable_javascript"
symbol_kind: "func"
signature: |
enum v7_err mg_enable_javascript(struct mg_mgr *m, struct v7 *v7,
const char *init_js_file_name);
---
Enables server-side JavaScript scripting.
Requires a `-DMG_ENABLE_JAVASCRIPT` compilation flag and V7 engine sources.
V7 instance must not be destroyed during manager's lifetime.
Returns a V7 error.
......@@ -4,7 +4,7 @@ decl_name: "mg_event_handler_t"
symbol_kind: "typedef"
signature: |
typedef void (*mg_event_handler_t)(struct mg_connection *nc, int ev,
void *ev_data);
void *ev_data MG_UD_ARG(void *user_data));
---
Callback function (event handler) prototype. Must be defined by the user.
......
......@@ -3,7 +3,7 @@ title: "mg_next()"
decl_name: "mg_next"
symbol_kind: "func"
signature: |
struct mg_connection *mg_next(struct mg_mgr *, struct mg_connection *);
struct mg_connection *mg_next(struct mg_mgr *mgr, struct mg_connection *c);
---
Iterates over all active connections.
......
......@@ -8,6 +8,7 @@ signature: |
unsigned int flags; /* Extra connection flags */
const char **error_string; /* Placeholder for the error string */
struct mg_iface *iface; /* Interface instance */
const char *nameserver; /* DNS server to use, NULL for default */
#if MG_ENABLE_SSL
/*
* SSL settings.
......
......@@ -14,9 +14,7 @@ signature: |
void *user_data; /* User data */
int num_ifaces;
struct mg_iface **ifaces; /* network interfaces */
#if MG_ENABLE_JAVASCRIPT
struct v7 *v7;
#endif
const char *nameserver; /* DNS server to use */
};
---
......
......@@ -4,9 +4,10 @@ decl_name: "struct mg_mgr_init_opts"
symbol_kind: "struct"
signature: |
struct mg_mgr_init_opts {
struct mg_iface_vtable *main_iface;
const struct mg_iface_vtable *main_iface;
int num_ifaces;
struct mg_iface_vtable **ifaces;
const struct mg_iface_vtable **ifaces;
const char *nameserver;
};
---
......
......@@ -6,6 +6,7 @@ items:
- { name: mg_resolve_async.md }
- { name: mg_resolve_async_opt.md }
- { name: mg_resolve_from_hosts_file.md }
- { name: mg_set_nameserver.md }
- { name: struct_mg_resolve_async_opts.md }
---
......
---
title: "mg_set_nameserver()"
decl_name: "mg_set_nameserver"
symbol_kind: "func"
signature: |
void mg_set_nameserver(struct mg_mgr *mgr, const char *nameserver);
---
Set default DNS server
......@@ -4,7 +4,7 @@ decl_name: "struct mg_resolve_async_opts"
symbol_kind: "struct"
signature: |
struct mg_resolve_async_opts {
const char *nameserver_url;
const char *nameserver;
int max_retries; /* defaults to 2 if zero */
int timeout; /* in seconds; defaults to 5 if zero */
int accept_literal; /* pseudo-resolve literal ipv4 and ipv6 addrs */
......
......@@ -3,6 +3,7 @@ title: "URI"
symbol_kind: "intro"
decl_name: "uri.h"
items:
- { name: mg_assemble_uri.md }
- { name: mg_parse_uri.md }
---
......
---
title: "mg_assemble_uri()"
decl_name: "mg_assemble_uri"
symbol_kind: "func"
signature: |
int mg_assemble_uri(const struct mg_str *scheme, const struct mg_str *user_info,
const struct mg_str *host, unsigned int port,
const struct mg_str *path, const struct mg_str *query,
const struct mg_str *fragment, int normalize_path,
struct mg_str *uri);
---
Assemble URI from parts. Any of the inputs can be NULL or zero-length mg_str.
If normalize_path is true, path is normalized by resolving relative refs.
Result is a heap-allocated string (uri->p must be free()d after use).
Returns 0 on success, -1 on error.
......@@ -3,7 +3,7 @@ title: "mg_parse_uri()"
decl_name: "mg_parse_uri"
symbol_kind: "func"
signature: |
int mg_parse_uri(struct mg_str uri, struct mg_str *scheme,
int mg_parse_uri(const struct mg_str uri, struct mg_str *scheme,
struct mg_str *user_info, struct mg_str *host,
unsigned int *port, struct mg_str *path, struct mg_str *query,
struct mg_str *fragment);
......
......@@ -8,20 +8,21 @@ items:
- { name: mg_basic_auth_header.md }
- { name: mg_conn_addr_to_str.md }
- { name: mg_fopen.md }
- { name: mg_fread.md }
- { name: mg_fwrite.md }
- { name: mg_hexdump.md }
- { name: mg_hexdump_connection.md }
- { name: mg_hexdumpf.md }
- { name: mg_is_big_endian.md }
- { name: mg_match_prefix.md }
- { name: mg_mbuf_append_base64.md }
- { name: mg_mbuf_append_base64_putc.md }
- { name: mg_next_comma_list_entry.md }
- { name: mg_open.md }
- { name: mg_skip.md }
- { name: mg_sock_addr_to_str.md }
- { name: mg_sock_to_str.md }
- { name: mg_start_thread.md }
- { name: mg_stat.md }
- { name: mg_url_encode.md }
---
......
......@@ -3,7 +3,8 @@ title: "mg_basic_auth_header()"
decl_name: "mg_basic_auth_header"
symbol_kind: "func"
signature: |
void mg_basic_auth_header(const char *user, const char *pass, struct mbuf *buf);
void mg_basic_auth_header(const struct mg_str user, const struct mg_str pass,
struct mbuf *buf);
---
Generate a Basic Auth header and appends it to buf.
......
......@@ -3,8 +3,8 @@ title: "mg_conn_addr_to_str()"
decl_name: "mg_conn_addr_to_str"
symbol_kind: "func"
signature: |
void mg_conn_addr_to_str(struct mg_connection *nc, char *buf, size_t len,
int flags);
int mg_conn_addr_to_str(struct mg_connection *c, char *buf, size_t len,
int flags);
---
Converts a connection's local or remote address into string.
......@@ -17,5 +17,6 @@ see `MG_SOCK_STRINGIFY_*` definitions.
- MG_SOCK_STRINGIFY_REMOTE - print remote peer's IP/port, not local address
If both port number and IP address are printed, they are separated by `:`.
If compiled with `-DMG_ENABLE_IPV6`, IPv6 addresses are supported.
If compiled with `-DMG_ENABLE_IPV6`, IPv6 addresses are supported.
Return length of the stringified address.
---
title: "mg_fread()"
decl_name: "mg_fread"
symbol_kind: "func"
signature: |
size_t mg_fread(void *ptr, size_t size, size_t count, FILE *f);
---
Reads data from the given file stream.
Return value is a number of bytes readen.
---
title: "mg_fwrite()"
decl_name: "mg_fwrite"
symbol_kind: "func"
signature: |
size_t mg_fwrite(const void *ptr, size_t size, size_t count, FILE *f);
---
Writes data to the given file stream.
Return value is a number of bytes wtitten.
---
title: "mg_match_prefix()"
decl_name: "mg_match_prefix"
symbol_kind: "func"
signature: |
int mg_match_prefix(const char *pattern, int pattern_len, const char *str);
---
Matches 0-terminated string (mg_match_prefix) or string with given length
mg_match_prefix_n against a glob pattern.
Match is case-insensitive. Returns number of bytes matched, or -1 if no
match.
---
title: "mg_next_comma_list_entry()"
decl_name: "mg_next_comma_list_entry"
symbol_kind: "func"
signature: |
const char *mg_next_comma_list_entry(const char *list, struct mg_str *val,
struct mg_str *eq_val);
---
A helper function for traversing a comma separated list of values.
It returns a list pointer shifted to the next value or NULL if the end
of the list found.
The value is stored in a val vector. If the value has a form "x=y", then
eq_val vector is initialised to point to the "y" part, and val vector length
is adjusted to point only to "x".
If the list is just a comma separated list of entries, like "aa,bb,cc" then
`eq_val` will contain zero-length string.
The purpose of this function is to parse comma separated string without
any copying/memory allocation.
......@@ -3,8 +3,8 @@ title: "mg_sock_addr_to_str()"
decl_name: "mg_sock_addr_to_str"
symbol_kind: "func"
signature: |
void mg_sock_addr_to_str(const union socket_address *sa, char *buf, size_t len,
int flags);
int mg_sock_addr_to_str(const union socket_address *sa, char *buf, size_t len,
int flags);
---
Convert the socket's address into string.
......
---
title: "mg_url_encode()"
decl_name: "mg_url_encode"
symbol_kind: "func"
signature: |
struct mg_str mg_url_encode(const struct mg_str src);
---
URL-escape the specified string.
All non-printable characters are escaped, plus `._-$,;~()/`.
Input need not be NUL-terminated, but the returned string is.
Returned string is heap-allocated and must be free()'d.
......@@ -16,7 +16,7 @@ CGI file must be executable. Mongoose honours the shebang line - see
http://en.wikipedia.org/wiki/Shebang_(Unix).
For example, if both PHP and Perl CGIs are used, then
``#!/path/to/php-cgi.exe` and ``#!/path/to/perl.exe` must be the first lines
`#!/path/to/php-cgi.exe` and `#!/path/to/perl.exe` must be the first lines
of the respective CGI scripts.
It is possible to hardcode the path to the CGI interpreter for all
......@@ -29,3 +29,7 @@ Example:
```c
opts.cgi_interpreter = "C:\\ruby\\ruby.exe";
```
NOTE: In the CGI handler we don't use explicitly a system call waitpid() for
reaping zombie processes. Instead, we set the SIGCHLD handler to SIG_IGN.
It will cause zombie processes to be reaped automatically.
CAUTION: not all OSes (e.g. QNX) reap zombies if SIGCHLD is ignored.
\ No newline at end of file
......@@ -18,8 +18,9 @@ static int exit_flag = 0;
static void ev_handler(struct mg_connection *c, int ev, void *p) {
if (ev == MG_EV_HTTP_REPLY) {
struct http_message *hm = (struct http_message *)p;
c->flags |= MG_F_CLOSE_IMMEDIATELY;
fwrite(hm->message.p, 1, hm->message.len, stdout);
fwrite(hm->message.p, 1, (int)hm->message.len, stdout);
putchar('\n');
exit_flag = 1;
} else if (ev == MG_EV_CLOSE) {
......@@ -31,7 +32,7 @@ int main(void) {
struct mg_mgr mgr;
mg_mgr_init(&mgr, NULL);
mg_connect_http(mgr, ev_handler, url, NULL, NULL);
mg_connect_http(&mgr, ev_handler, url, NULL, NULL);
while (exit_flag == 0) {
......
......@@ -30,8 +30,8 @@ static void ev_handler(struct mg_connection *c, int ev, void *p) {
// We have received an HTTP request. Parsed request is contained in `hm`.
// Send HTTP reply to the client which shows full original request.
mg_send_head(c, 200, hm.message.len, "Content-Type: text/plain");
mg_printf(c, "%.*s", hm.message.len, hm.message.p);
mg_send_head(c, 200, hm->message.len, "Content-Type: text/plain");
mg_printf(c, "%.*s", (int)hm->message.len, hm->message.p);
}
}
......
......@@ -35,7 +35,7 @@ The exec directive is used to execute a command on a server,
and show command's output. Example: `<!--#exec "ls -l" -->`
The call directive is a way to invoke a C handler from the HTML page.
On each occurence of `<!--#call PARAMS -->` directive,
On each occurrence of `<!--#call PARAMS -->` directive,
Mongoose calls a registered event handler with `MG_EV_SSI_CALL` event.
Event parameter will point to the `PARAMS` string.
An event handler can output any text, for example by calling
......
......@@ -30,4 +30,4 @@ int main(void) {
}
```
For the full example, please see the [Simplest HTTPS server example](https://github.com/cesanta/dev/tree/master/mongoose/examples/simplest_web_server_ssl).
For the full example, please see the [Simplest HTTPS server example](https://github.com/cesanta/mongoose/tree/master/examples/simplest_web_server_ssl).
......@@ -3,6 +3,6 @@ title: Disabling flags
---
- `MG_DISABLE_HTTP_DIGEST_AUTH` disable HTTP Digest (MD5) authorisation support
- `MG_DISABLE_SHA1` disable SHA1 support (used by WebSocket)
- `MG_DISABLE_MD5` disable MD5 support (used by HTTP auth)
- `CS_DISABLE_SHA1` disable SHA1 support (used by WebSocket)
- `CS_DISABLE_MD5` disable MD5 support (used by HTTP auth)
- `MG_DISABLE_HTTP_KEEP_ALIVE` useful for embedded systems to save resources
......@@ -9,3 +9,4 @@ title: Tunables
- `MG_SSL_CRYPTO_MODERN`, `MG_SSL_CRYPTO_OLD` - choose either "Modern" or "Old" ciphers
instead of the default "Intermediate" setting.
See [this article](https://wiki.mozilla.org/Security/Server_Side_TLS#Recommended_configurations) for details.
- `MG_USER_FILE_FUNCTIONS` allow you to use custom file operation, by defining you own `mg_stat`, `mg_fopen`, `mg_open`, `mg_fread` and `mg_fwrite` functions
\ No newline at end of file
......@@ -22,7 +22,7 @@ IPATH = . ../.. $(REPO_PATH)
VPATH = ../..
MONGOOSE_FEATURES = -DMG_ENABLE_SSL -DMG_ENABLE_HTTP_STREAMING_MULTIPART
MONGOOSE_FEATURES = -DMG_ENABLE_SSL -DMG_ENABLE_HTTP_STREAMING_MULTIPART -DMG_MODULE_LINES
SDK_FLAGS = -DUSE_FREERTOS -DSL_PLATFORM_MULTI_THREADED
# -DTARGET_IS_CC3200 would reduce code size by using functions in ROM
......@@ -58,11 +58,11 @@ $(FW_DIR):
$(FW_ZIP): $(FW_ELF) $(FW_BIN) $(SLFS_FILES)
@echo " Code size: $(shell ls -l $(FW_BIN) | awk '{print $$5}')"
@echo " GEN $(FW_MANIFEST)"
@fw_meta gen_build_info \
@fw_meta.py gen_build_info \
--json_output=$(BUILD_INFO_JSON)
@cp -v $(SLFS_FILES) out/
@cp $(CC3200_SP_FILE)* $(FW_DIR)
@fw_meta create_manifest \
@fw_meta.py create_manifest \
--name=$(PROG) --platform=$(PLATFORM) \
--build_info=$(BUILD_INFO_JSON) \
--output=$(FW_MANIFEST) \
......@@ -72,14 +72,14 @@ $(FW_ZIP): $(FW_ELF) $(FW_BIN) $(SLFS_FILES)
/sys/mcuimg.bin:type=app,src=$(notdir $(FW_BIN)) \
$(foreach f,$(SLFS_FILES), $(notdir $(f)):type=slfile,src=$(notdir $(f)))
@echo " ZIP $@"
@fw_meta create_fw \
@fw_meta.py create_fw \
--manifest=$(FW_MANIFEST) \
--src_dir=$(FW_DIR) \
--output=$@
FREERTOS_SRCS = timers.c list.c queue.c tasks.c port.c heap_3.c osi_freertos.c
DRIVER_SRCS = cpu.c gpio.c gpio_if.c i2c.c i2c_if.c interrupt.c pin.c prcm.c spi.c uart.c udma.c utils.c
SL_SRCS = socket.c wlan.c driver.c device.c netapp.c netcfg.c network_common.c cc_pal.c fs.c
SL_SRCS = socket.c wlan.c driver.c device.c netapp.c netcfg.c network_common.c timer.c cc_pal.c fs.c
SDK_SRCS = startup_gcc.c $(FREERTOS_SRCS) $(DRIVER_SRCS) $(SL_SRCS)
IPATH += $(SDK_PATH) $(SDK_PATH)/inc $(SDK_PATH)/driverlib \
$(SDK_PATH)/example/common $(SDK_PATH)/oslib \
......
......@@ -40,22 +40,22 @@ void cs_log_set_level(enum cs_log_level level);
void cs_log_set_file(FILE *file);
extern enum cs_log_level cs_log_level;
extern enum cs_log_level cs_log_threshold;
void cs_log_print_prefix(const char *func);
void cs_log_printf(const char *fmt, ...);
#define LOG(l, x) \
if (cs_log_level >= l) { \
if (cs_log_threshold >= l) { \
cs_log_print_prefix(__func__); \
cs_log_printf x; \
}
#ifndef CS_NDEBUG
#define DBG(x) \
if (cs_log_level >= LL_VERBOSE_DEBUG) { \
cs_log_print_prefix(__func__); \
cs_log_printf x; \
#define DBG(x) \
if (cs_log_threshold >= LL_VERBOSE_DEBUG) { \
cs_log_print_prefix(__func__); \
cs_log_printf x; \
}
#else /* NDEBUG */
......
......@@ -294,3 +294,16 @@ void SimpleLinkGeneralEventHandler(SlDeviceEvent_t *e) {
LOG(LL_ERROR, ("status %d sender %d", e->EventData.deviceEvent.status,
e->EventData.deviceEvent.sender));
}
#ifndef __TI_COMPILER_VERSION__
int _gettimeofday_r(struct _reent *r, struct timeval *tp, void *tz) {
#else
int gettimeofday(struct timeval *tp, void *tz) {
#endif
unsigned long sec;
unsigned short msec;
MAP_PRCMRTCGet(&sec, &msec);
tp->tv_sec = sec;
tp->tv_usec = ((unsigned long) msec) * 1000;
return 0;
}
docker.cesanta.com/cc3200-build:1.2.0-r8
docker.cesanta.com/cc3200-build:1.3.0-r2
SDK_VER=$(shell cat sdk.version)
.PHONY: all
MG_PATH = $(realpath $(PWD)/../../)
all:
docker run --rm -it -v $(MG_PATH):/esp32_idf \
$(SDK_VER) \
bash -c "cd esp32_idf/examples/ESP32_IDF && \
make -f Makefile.build defconfig && make -f Makefile.build"
clean:
docker run --rm -it -v $(MG_PATH):/esp32_idf \
$(SDK_VER) \
bash -c "rm -rf esp32_idf/examples/ESP32_IDF/build"
#
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
# project subdirectory.
#
PROJECT_NAME := esp32_idf
include $(IDF_PATH)/make/project.mk
This is a Mongoose "Hello, world" that can be compiled under Espressif IoT Development Framework for ESP32
It connects to WiFi network and serves a "hello world" page.
Most of the the boilerplate comes from [project_template](https://github.com/espressif/esp-idf-template) with minimal changes.
For building the example, you need to have [Docker](https://www.docker.com/products/docker) and use our pre-built SDK container.
To build just run in the example directory
```
$ make
```
Note: before building, change `WIFI_SSID` and `WIFI_PASS` macros in main/main.c file
Once built, use [esptool](https://github.com/espressif/esptool) for flashing
```
$ python esptool.py --chip esp32 --port /dev/ttyUSB0 --baud 115200 --before default_reset --after hard_reset write_flash -u --flash_mode dio --flash_freq 40m --flash_size detect 0x1000 build/bootloader/bootloader.bin 0x10000 build/esp32_idf.bin 0x8000 build/partitions_singleapp.bin
```
#
# Main component makefile.
#
# This Makefile can be left empty. By default, it will take the sources in the
# src/ directory, compile them and link them into lib(subdirectory_name).a
# in the build directory. This behaviour is entirely configurable,
# please read the ESP-IDF documents if you need to do this.
#
COMPONENT_OBJS = main.o mongoose.o
mongoose.o: ../../../../mongoose.c
$(summary) "CC $@"
$(CC) $(CFLAGS) $(CPPFLAGS) \
$(addprefix -I ,$(COMPONENT_INCLUDES)) \
$(addprefix -I ,$(COMPONENT_EXTRA_INCLUDES)) \
-c $< -o $@
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "esp_event.h"
#include "esp_event_loop.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "nvs_flash.h"
#include "./../../../mongoose.h"
#define WIFI_SSID "ssid"
#define WIFI_PASS "pass"
#define MG_LISTEN_ADDR "80"
static esp_err_t event_handler(void *ctx, system_event_t *event) {
(void) ctx;
(void) event;
return ESP_OK;
}
static void mg_ev_handler(struct mg_connection *nc, int ev, void *p) {
static const char *reply_fmt =
"HTTP/1.0 200 OK\r\n"
"Connection: close\r\n"
"Content-Type: text/plain\r\n"
"\r\n"
"Hello %s\n";
switch (ev) {
case MG_EV_ACCEPT: {
char addr[32];
mg_sock_addr_to_str(&nc->sa, addr, sizeof(addr),
MG_SOCK_STRINGIFY_IP | MG_SOCK_STRINGIFY_PORT);
printf("Connection %p from %s\n", nc, addr);
break;
}
case MG_EV_HTTP_REQUEST: {
char addr[32];
struct http_message *hm = (struct http_message *) p;
mg_sock_addr_to_str(&nc->sa, addr, sizeof(addr),
MG_SOCK_STRINGIFY_IP | MG_SOCK_STRINGIFY_PORT);
printf("HTTP request from %s: %.*s %.*s\n", addr, (int) hm->method.len,
hm->method.p, (int) hm->uri.len, hm->uri.p);
mg_printf(nc, reply_fmt, addr);
nc->flags |= MG_F_SEND_AND_CLOSE;
break;
}
case MG_EV_CLOSE: {
printf("Connection %p closed\n", nc);
break;
}
}
}
void app_main(void) {
nvs_flash_init();
tcpip_adapter_init();
ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL));
/* Initializing WiFi */
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
wifi_config_t sta_config = {
.sta = {.ssid = WIFI_SSID, .password = WIFI_PASS, .bssid_set = false}};
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &sta_config));
ESP_ERROR_CHECK(esp_wifi_start());
ESP_ERROR_CHECK(esp_wifi_connect());
/* Starting Mongoose */
struct mg_mgr mgr;
struct mg_connection *nc;
printf("Starting web-server on port %s\n", MG_LISTEN_ADDR);
mg_mgr_init(&mgr, NULL);
nc = mg_bind(&mgr, MG_LISTEN_ADDR, mg_ev_handler);
if (nc == NULL) {
printf("Error setting up listener!\n");
return;
}
mg_set_protocol_http_websocket(nc);
/* Processing events */
while (1) {
mg_mgr_poll(&mgr, 1000);
}
}
docker.cesanta.com/esp32-build:1.0-r13
#!/bin/bash
REPO=$(cd ../.. && pwd)
docker run \
--rm -i -v $(realpath ${PWD}/../..):/src \
--rm -i -v $REPO:/src \
--entrypoint=/bin/bash $(cat sdk.version) -l -c -x '
export SDK_PATH=/opt/Espressif/ESP8266_RTOS_SDK;
export BIN_PATH=./bin;
......
......@@ -3,7 +3,7 @@
# `wildcard ./*/` works in both linux and linux/wine, while `wildcard */` enumerates nothing under wine
SUBDIRS = $(sort $(dir $(wildcard ./*/)))
SUBDIRS:=$(filter-out ./ ./CC3200/ ./ESP8266_RTOS/ ./mbed/ ./MSP432/ ./nRF51/ ./nRF52/ ./NXP_K64/ ./NXP_LPC4088/ ./PIC32/ ./STM32F4_CC3100/ ./TM4C129/ ./WinCE/, $(SUBDIRS))
SUBDIRS:=$(filter-out ./ ./CC3200/ ./ESP32_IDF/ ./ESP8266_RTOS/ ./mbed/ ./MSP432/ ./nRF51/ ./nRF52/ ./NXP_K64/ ./NXP_LPC4088/ ./PIC32/ ./STM32F4_CC3100/ ./TM4C129/ ./WinCE/, $(SUBDIRS))
ifeq ($(OS), Windows_NT)
SUBDIRS:=$(filter-out ./netcat/ ./raspberry_pi_mjpeg_led/ ./captive_dns_server/, $(SUBDIRS))
......
......@@ -10,28 +10,13 @@
#include "mongoose.h"
static const char *s_http_port = "8000";
static struct mg_serve_http_opts s_http_server_opts;
struct file_writer_data {
FILE *fp;
size_t bytes_written;
};
static void handle_request(struct mg_connection *nc) {
// This handler gets for all endpoints but /upload
mg_printf(nc, "%s",
"HTTP/1.1 200 OK\r\n"
"Content-Type: text/html\r\n"
"Connection: close\r\n"
"\r\n"
"<html><body>Upload example."
"<form method=\"POST\" action=\"/upload\" "
" enctype=\"multipart/form-data\">"
"<input type=\"file\" name=\"file\" /> <br/>"
"<input type=\"submit\" value=\"Upload\" />"
"</form></body></html>");
nc->flags |= MG_F_SEND_AND_CLOSE;
}
static void handle_upload(struct mg_connection *nc, int ev, void *p) {
struct file_writer_data *data = (struct file_writer_data *) nc->user_data;
struct mg_http_multipart_part *mp = (struct mg_http_multipart_part *) p;
......@@ -82,25 +67,27 @@ static void handle_upload(struct mg_connection *nc, int ev, void *p) {
}
static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
(void) ev_data;
switch (ev) {
case MG_EV_HTTP_REQUEST:
// Invoked when the full HTTP request is in the buffer (including body).
handle_request(nc);
break;
if (ev == MG_EV_HTTP_REQUEST) {
mg_serve_http(nc, ev_data, s_http_server_opts);
}
}
int main(void) {
struct mg_mgr mgr;
struct mg_connection *nc;
struct mg_connection *c;
mg_mgr_init(&mgr, NULL);
nc = mg_bind(&mgr, s_http_port, ev_handler);
c = mg_bind(&mgr, s_http_port, ev_handler);
if (c == NULL) {
fprintf(stderr, "Cannot start server on port %s\n", s_http_port);
exit(EXIT_FAILURE);
}
s_http_server_opts.document_root = "."; // Serve current directory
mg_register_http_endpoint(c, "/upload", handle_upload MG_UD_ARG(NULL));
mg_register_http_endpoint(nc, "/upload", handle_upload);
// Set up HTTP server parameters
mg_set_protocol_http_websocket(nc);
mg_set_protocol_http_websocket(c);
printf("Starting web server on port %s\n", s_http_port);
for (;;) {
......
<!DOCTYPE html>
<html>
<head>
<title>AJAX Upload Example</title>
<script src="//code.jquery.com/jquery-1.9.1.js"></script>
<script type="text/javascript">
function updateProgress(evt) {
if (evt.lengthComputable) {
document.getElementById("output").textContent =
"Uploaded " + evt.loaded + " of " + evt.total + " bytes";
}
}
function uploadFile() {
var file_data = new FormData(document.getElementById('filename'));
$.ajax({
url: "/upload",
type: "POST",
data: file_data,
processData: false,
contentType: false,
cache: false,
xhr: function() {
myXhr = $.ajaxSettings.xhr();
if(myXhr.upload){
myXhr.upload.addEventListener('progress',updateProgress, false); // for handling the progress of the upload
}
return myXhr;
},
}).done(function(data) {
document.getElementById("output").textContent = "Result: " + data;
});
return false;
}
</script>
</head>
<body>
<h1>Upload file using standard form upload</h1>
<form method="POST" action="/upload" enctype="multipart/form-data">
<label>Select a file:</label><br>
<input type="file" name="file" />
<input type="submit" value="Upload" />
</form>
<h1>Upload file using Ajax - that also gives progress report</h1>
<form method="post" id="filename" name="filename" onsubmit="return uploadFile();">
<label>Select a file:</label><br>
<input type="file" id="file" name="file" required />
<input type="submit" value="Upload" />
</form>
<br><br><div id="output"></div>
</body>
</html>
PROG = mqtt_broker
MODULE_CFLAGS = -DMG_ENABLE_MQTT_BROKER -DMG_ENABLE_HTTP=0
SSL_LIB=openssl
#SSL_LIB=openssl
include ../examples.mk
......@@ -17,22 +17,31 @@
#include "../../mongoose.h"
static const char *s_listening_address = "0.0.0.0:1883";
static void ev_handler(struct mg_connection *c, int ev, void *ev_data) {
if (ev != MG_EV_POLL) printf("USER HANDLER GOT EVENT %d\n", ev);
/* Do your custom event processing here */
mg_mqtt_broker(c, ev, ev_data);
}
int main(void) {
struct mg_mgr mgr;
const char *address = "0.0.0.0:1883";
struct mg_connection *nc;
struct mg_connection *c;
struct mg_mqtt_broker brk;
mg_mgr_init(&mgr, NULL);
mg_mqtt_broker_init(&brk, NULL);
if ((nc = mg_bind(&mgr, address, mg_mqtt_broker)) == NULL) {
fprintf(stderr, "mg_bind(%s) failed\n", address);
if ((c = mg_bind(&mgr, s_listening_address, ev_handler)) == NULL) {
fprintf(stderr, "mg_bind(%s) failed\n", s_listening_address);
exit(EXIT_FAILURE);
}
nc->user_data = &brk;
mg_mqtt_broker_init(&brk, NULL);
c->user_data = &brk;
mg_set_protocol_mqtt(c);
printf("MQTT broker started on %s\n", address);
printf("MQTT broker started on %s\n", s_listening_address);
/*
* TODO: Add a HTTP status page that shows current sessions
......
......@@ -27,10 +27,7 @@ static void ev_handler(struct mg_connection *nc, int ev, void *p) {
struct mg_mqtt_message *msg = (struct mg_mqtt_message *) p;
(void) nc;
#if 0
if (ev != MG_EV_POLL)
printf("USER HANDLER GOT %d\n", ev);
#endif
if (ev != MG_EV_POLL) printf("USER HANDLER GOT EVENT %d\n", ev);
switch (ev) {
case MG_EV_CONNECT: {
......
PROG = mqtt_over_websocket_server
MODULE_CFLAGS = -DMG_ENABLE_MQTT_BROKER=1
#SSL_LIB=mbedtls
include ../examples.mk
/*
* Copyright (c) 2014 Cesanta Software Limited
* All rights reserved
* This software is dual-licensed: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. For the terms of this
* license, see <http://www.gnu.org/licenses/>.
*
* You are free to use this software under the terms of the GNU General
* Public License, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* Alternatively, you can license this software under a commercial
* license, as set out in <https://www.cesanta.com/license>.
*/
#include "mongoose.h"
static const char *s_mqtt_address = "0.0.0.0:1883";
static const char *s_http_address = "0.0.0.0:8080";
static void unproxy(struct mg_connection *c) {
struct mg_connection *pc = (struct mg_connection *) c->user_data;
if (pc != NULL) {
pc->flags |= MG_F_CLOSE_IMMEDIATELY;
pc->user_data = NULL;
c->user_data = NULL;
}
printf("Closing connection %p\n", c);
}
static void proxy_handler(struct mg_connection *c, int ev, void *ev_data) {
if (ev == MG_EV_POLL) return;
printf("%p %s EVENT %d %p\n", c, __func__, ev, ev_data);
switch (ev) {
case MG_EV_CLOSE: {
unproxy(c);
break;
}
case MG_EV_RECV: {
struct mg_connection *pc = (struct mg_connection *) c->user_data;
if (pc != NULL) {
mg_send_websocket_frame(pc, WEBSOCKET_OP_BINARY, c->recv_mbuf.buf,
c->recv_mbuf.len);
mbuf_remove(&c->recv_mbuf, c->recv_mbuf.len);
}
break;
}
}
}
static void http_handler(struct mg_connection *c, int ev, void *ev_data) {
struct mg_connection *pc = (struct mg_connection *) c->user_data;
if (ev == MG_EV_POLL) return;
printf("%p %s EVENT %d %p\n", c, __func__, ev, ev_data);
/* Do your custom event processing here */
switch (ev) {
case MG_EV_WEBSOCKET_HANDSHAKE_DONE: {
pc = mg_connect(c->mgr, s_mqtt_address, proxy_handler);
pc->user_data = c;
c->user_data = pc;
printf("Created proxy connection %p\n", pc);
break;
}
case MG_EV_WEBSOCKET_FRAME: {
struct websocket_message *wm = (struct websocket_message *) ev_data;
if (pc != NULL) {
printf("Forwarding %d bytes\n", (int) wm->size);
mg_send(pc, wm->data, wm->size);
}
break;
}
case MG_EV_CLOSE: {
unproxy(c);
break;
}
}
}
static void mqtt_handler(struct mg_connection *c, int ev, void *ev_data) {
if (ev == MG_EV_POLL) return;
printf("%p %s EVENT %d %p\n", c, __func__, ev, ev_data);
/* Do your custom event processing here */
switch (ev) {
case MG_EV_CLOSE:
printf("Closing MQTT connection %p\n", c);
break;
}
mg_mqtt_broker(c, ev, ev_data);
}
static void start_mqtt_server(struct mg_mgr *mgr, const char *addr) {
struct mg_connection *c;
static struct mg_mqtt_broker brk; // static is important - must not perish
if ((c = mg_bind(mgr, addr, mqtt_handler)) == NULL) {
fprintf(stderr, "Cannot start MQTT server on port [%s]\n", addr);
exit(EXIT_FAILURE);
}
mg_mqtt_broker_init(&brk, NULL);
c->user_data = &brk;
mg_set_protocol_mqtt(c);
printf("MQTT server started on %s\n", addr);
}
static void start_http_server(struct mg_mgr *mgr, const char *addr) {
struct mg_connection *c;
if ((c = mg_bind(mgr, addr, http_handler)) == NULL) {
fprintf(stderr, "Cannot start HTTP server on port [%s]\n", addr);
exit(EXIT_FAILURE);
}
mg_set_protocol_http_websocket(c);
printf("HTTP server started on %s\n", addr);
}
int main(void) {
struct mg_mgr mgr;
mg_mgr_init(&mgr, NULL);
start_http_server(&mgr, s_http_address);
start_mqtt_server(&mgr, s_mqtt_address);
for (;;) {
mg_mgr_poll(&mgr, 1000);
}
}
PROG = multithreaded
MODULE_CFLAGS=-DMG_ENABLE_THREADS
include ../examples.mk
/*
* Copyright (c) 2014-2017 Cesanta Software Limited
* All rights reserved
*/
#include "mongoose.h"
static sig_atomic_t s_received_signal = 0;
static const char *s_http_port = "8000";
static const int s_num_worker_threads = 5;
static unsigned long s_next_id = 0;
static void signal_handler(int sig_num) {
signal(sig_num, signal_handler);
s_received_signal = sig_num;
}
static struct mg_serve_http_opts s_http_server_opts;
static sock_t sock[2];
// This info is passed to the worker thread
struct work_request {
unsigned long conn_id; // needed to identify the connection where to send the reply
// optionally, more data that could be required by worker
};
// This info is passed by the worker thread to mg_broadcast
struct work_result {
unsigned long conn_id;
int sleep_time;
};
static void on_work_complete(struct mg_connection *nc, int ev, void *ev_data) {
(void) ev;
char s[32];
struct mg_connection *c;
for (c = mg_next(nc->mgr, NULL); c != NULL; c = mg_next(nc->mgr, c)) {
if (c->user_data != NULL) {
struct work_result *res = (struct work_result *)ev_data;
if ((unsigned long)c->user_data == res->conn_id) {
sprintf(s, "conn_id:%lu sleep:%d", res->conn_id, res->sleep_time);
mg_send_head(c, 200, strlen(s), "Content-Type: text/plain");
mg_printf(c, "%s", s);
}
}
}
}
void *worker_thread_proc(void *param) {
struct mg_mgr *mgr = (struct mg_mgr *) param;
struct work_request req = {0};
while (s_received_signal == 0) {
if (read(sock[1], &req, sizeof(req)) < 0)
perror("Reading worker sock");
int r = rand() % 10;
sleep(r);
struct work_result res = {req.conn_id, r};
mg_broadcast(mgr, on_work_complete, (void *)&res, sizeof(res));
}
return NULL;
}
static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
(void) nc;
(void) ev_data;
switch (ev) {
case MG_EV_ACCEPT:
nc->user_data = (void *)++s_next_id;
break;
case MG_EV_HTTP_REQUEST: {
struct work_request req = {(unsigned long)nc->user_data};
if (write(sock[0], &req, sizeof(req)) < 0)
perror("Writing worker sock");
break;
}
case MG_EV_CLOSE: {
if (nc->user_data) nc->user_data = NULL;
}
}
}
int main(void) {
struct mg_mgr mgr;
struct mg_connection *nc;
int i;
if (mg_socketpair(sock, SOCK_STREAM) == 0) {
perror("Opening socket pair");
exit(1);
}
signal(SIGTERM, signal_handler);
signal(SIGINT, signal_handler);
mg_mgr_init(&mgr, NULL);
nc = mg_bind(&mgr, s_http_port, ev_handler);
if (nc == NULL) {
printf("Failed to create listener\n");
return 1;
}
mg_set_protocol_http_websocket(nc);
s_http_server_opts.document_root = "."; // Serve current directory
s_http_server_opts.enable_directory_listing = "no";
for (i = 0; i < s_num_worker_threads; i++) {
mg_start_thread(worker_thread_proc, &mgr);
}
printf("Started on port %s\n", s_http_port);
while (s_received_signal == 0) {
mg_mgr_poll(&mgr, 200);
}
mg_mgr_free(&mgr);
closesocket(sock[0]);
closesocket(sock[1]);
return 0;
}
......@@ -3,7 +3,7 @@ PROJECT_NAME := iot_lwip_tcp_server_pca10028
export OUTPUT_FILENAME
#MAKEFILE_NAME := $(CURDIR)/$(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))
MAKEFILE_NAME := $(MAKEFILE_LIST)
MAKEFILE_DIR := $(dir $(MAKEFILE_NAME) )
MAKEFILE_DIR := $(dir $(MAKEFILE_NAME) )
TEMPLATE_PATH = ../../../../nrf51_iot_sdk/components/toolchain/gcc
ifeq ($(OS),Windows_NT)
......@@ -17,7 +17,7 @@ RM := rm -rf
#echo suspend
ifeq ("$(VERBOSE)","1")
NO_ECHO :=
NO_ECHO :=
else
NO_ECHO := @
endif
......@@ -118,7 +118,7 @@ BUILD_DIRECTORIES := $(sort $(OBJECT_DIRECTORY) $(OUTPUT_BINARY_DIRECTORY) $(LIS
# Mongoose features
MG_FEATURES_TINY = \
-DMG_DISABLE_HTTP_DIGEST_AUTH \
-DMG_DISABLE_MD5 \
-DCS_DISABLE_MD5 \
-DMG_DISABLE_HTTP_KEEP_ALIVE \
-DMG_ENABLE_HTTP_SSI=0 \
-DMG_ENABLE_HTTP_STREAMING_MULTIPART
......@@ -251,7 +251,7 @@ genbin:
$(NO_ECHO)$(OBJCOPY) -O binary $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).bin
## Create binary .hex file from the .out file
genhex:
genhex:
@echo Preparing: $(OUTPUT_FILENAME).hex
$(NO_ECHO)$(OBJCOPY) -O ihex $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).hex
......
......@@ -3,7 +3,7 @@ PROJECT_NAME := iot_lwip_tcp_server_pca10040
export OUTPUT_FILENAME
#MAKEFILE_NAME := $(CURDIR)/$(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))
MAKEFILE_NAME := $(MAKEFILE_LIST)
MAKEFILE_DIR := $(dir $(MAKEFILE_NAME) )
MAKEFILE_DIR := $(dir $(MAKEFILE_NAME) )
TEMPLATE_PATH = ../../../../nrf5_iot_sdk/components/toolchain/gcc
ifeq ($(OS),Windows_NT)
......@@ -17,7 +17,7 @@ RM := rm -rf
#echo suspend
ifeq ("$(VERBOSE)","1")
NO_ECHO :=
NO_ECHO :=
else
NO_ECHO := @
endif
......@@ -165,7 +165,7 @@ BUILD_DIRECTORIES := $(sort $(OBJECT_DIRECTORY) $(OUTPUT_BINARY_DIRECTORY) $(LIS
# Mongoose features
MG_FEATURES_TINY = \
-DMG_DISABLE_HTTP_DIGEST_AUTH \
-DMG_DISABLE_MD5 \
-DCS_DISABLE_MD5 \
-DMG_DISABLE_HTTP_KEEP_ALIVE \
-DMG_ENABLE_HTTP_SSI=0 \
-DMG_ENABLE_HTTP_STREAMING_MULTIPART
......@@ -297,7 +297,7 @@ genbin:
$(NO_ECHO)$(OBJCOPY) -O binary $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).bin
## Create binary .hex file from the .out file
genhex:
genhex:
@echo Preparing: $(OUTPUT_FILENAME).hex
$(NO_ECHO)$(OBJCOPY) -O ihex $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).hex
echosize:
......
PROG = websocket_chat
MODULE_CFLAGS = -DMG_ENABLE_FILESYSTEM=0
MODULE_CFLAGS = -DMG_ENABLE_FILESYSTEM=1
include ../examples.mk
......@@ -7,6 +7,7 @@
static sig_atomic_t s_signal_received = 0;
static const char *s_http_port = "8000";
static struct mg_serve_http_opts s_http_server_opts;
static void signal_handler(int sig_num) {
signal(sig_num, signal_handler); // Reinstantiate signal handler
......@@ -46,6 +47,10 @@ static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
broadcast(nc, d);
break;
}
case MG_EV_HTTP_REQUEST: {
mg_serve_http(nc, (struct http_message *) ev_data, s_http_server_opts);
break;
}
case MG_EV_CLOSE: {
/* Disconnect. Tell everybody. */
if (is_websocket(nc)) {
......@@ -69,6 +74,8 @@ int main(void) {
nc = mg_bind(&mgr, s_http_port, ev_handler);
mg_set_protocol_http_websocket(nc);
s_http_server_opts.document_root = "."; // Serve current directory
s_http_server_opts.enable_directory_listing = "yes";
printf("Started on port %s\n", s_http_port);
while (s_signal_received == 0) {
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -23,7 +23,7 @@
#ifndef CS_MONGOOSE_SRC_COMMON_H_
#define CS_MONGOOSE_SRC_COMMON_H_
#define MG_VERSION "6.7"
#define MG_VERSION "6.8"
/* Local tweaks, applied before any of Mongoose's own headers. */
#ifdef MG_LOCALS
......@@ -46,9 +46,10 @@
#define CS_P_WINDOWS 2
#define CS_P_ESP32 15
#define CS_P_ESP8266 3
#define CS_P_CC3100 6
#define CS_P_CC3200 4
#define CS_P_CC3220 17
#define CS_P_MSP432 5
#define CS_P_CC3100 6
#define CS_P_TM4C129 14
#define CS_P_MBED 7
#define CS_P_WINCE 8
......@@ -58,15 +59,17 @@
#define CS_P_NRF52 10
#define CS_P_PIC32 11
#define CS_P_STM32 16
/* Next id: 17 */
/* Next id: 18 */
/* If not specified explicitly, we guess platform by defines. */
#ifndef CS_PLATFORM
#if defined(TARGET_IS_MSP432P4XX) || defined(__MSP432P401R__)
#define CS_PLATFORM CS_P_MSP432
#elif defined(cc3200)
#elif defined(cc3200) || defined(TARGET_IS_CC3200)
#define CS_PLATFORM CS_P_CC3200
#elif defined(cc3220) || defined(TARGET_IS_CC3220)
#define CS_PLATFORM CS_P_CC3220
#elif defined(__unix__) || defined(__APPLE__)
#define CS_PLATFORM CS_P_UNIX
#elif defined(WINCE)
......@@ -111,8 +114,9 @@
/* Amalgamated: #include "common/platforms/platform_windows.h" */
/* Amalgamated: #include "common/platforms/platform_esp32.h" */
/* Amalgamated: #include "common/platforms/platform_esp8266.h" */
/* Amalgamated: #include "common/platforms/platform_cc3200.h" */
/* Amalgamated: #include "common/platforms/platform_cc3100.h" */
/* Amalgamated: #include "common/platforms/platform_cc3200.h" */
/* Amalgamated: #include "common/platforms/platform_cc3220.h" */
/* Amalgamated: #include "common/platforms/platform_mbed.h" */
/* Amalgamated: #include "common/platforms/platform_nrf51.h" */
/* Amalgamated: #include "common/platforms/platform_nrf52.h" */
......@@ -195,6 +199,7 @@
#include <stdlib.h>
#include <sys/stat.h>
#include <time.h>
#include <ctype.h>
#ifdef _MSC_VER
#pragma comment(lib, "ws2_32.lib") /* Linking with winsock library */
......@@ -221,15 +226,13 @@
#define __func__ __FILE__ ":" STR(__LINE__)
#endif
#define snprintf _snprintf
#define fileno _fileno
#define vsnprintf _vsnprintf
#define sleep(x) Sleep((x) *1000)
#define to64(x) _atoi64(x)
#if !defined(__MINGW32__) && !defined(__MINGW64__)
#define popen(x, y) _popen((x), (y))
#define pclose(x) _pclose(x)
#define fileno _fileno
#endif
#define rmdir _rmdir
#if defined(_MSC_VER) && _MSC_VER >= 1400
#define fseeko(x, y, z) _fseeki64((x), (y), (z))
#else
......@@ -320,6 +323,9 @@ typedef struct _stati64 cs_stat_t;
#define MG_NET_IF MG_NET_IF_SOCKET
#endif
int rmdir(const char *dirname);
unsigned int sleep(unsigned int seconds);
#endif /* CS_PLATFORM == CS_P_WINDOWS */
#endif /* CS_COMMON_PLATFORMS_PLATFORM_WINDOWS_H_ */
#ifdef MG_MODULE_LINES
......@@ -459,6 +465,14 @@ typedef struct stat cs_stat_t;
#define MG_NET_IF MG_NET_IF_SOCKET
#endif
#ifndef MG_HOSTS_FILE_NAME
#define MG_HOSTS_FILE_NAME "/etc/hosts"
#endif
#ifndef MG_RESOLV_CONF_FILE_NAME
#define MG_RESOLV_CONF_FILE_NAME "/etc/resolv.conf"
#endif
#endif /* CS_PLATFORM == CS_P_UNIX */
#endif /* CS_COMMON_PLATFORMS_PLATFORM_UNIX_H_ */
#ifdef MG_MODULE_LINES
......@@ -529,7 +543,9 @@ typedef struct stat cs_stat_t;
#define SIZE_T_FMT "u"
typedef struct stat cs_stat_t;
#define DIRSEP '/'
#if !defined(MGOS_VFS_DEFINE_DIRENT)
#define CS_DEFINE_DIRENT
#endif
#define to64(x) strtoll(x, NULL, 10)
#define INT64_FMT PRId64
......@@ -537,7 +553,7 @@ typedef struct stat cs_stat_t;
#define __cdecl
#define _FILE_OFFSET_BITS 32
#ifndef RTOS_SDK
#if !defined(RTOS_SDK) && !defined(__cplusplus)
#define fileno(x) -1
#endif
......@@ -549,9 +565,9 @@ typedef struct stat cs_stat_t;
#ifndef MG_NET_IF
#include <lwip/opt.h>
#if LWIP_SOCKET /* RTOS SDK has LWIP sockets */
# define MG_NET_IF MG_NET_IF_SOCKET
#define MG_NET_IF MG_NET_IF_SOCKET
#else
# define MG_NET_IF MG_NET_IF_LWIP_LOW_LEVEL
#define MG_NET_IF MG_NET_IF_LWIP_LOW_LEVEL
#endif
#endif
......@@ -592,7 +608,7 @@ typedef struct stat cs_stat_t;
#include <simplelink.h>
#include <netapp.h>
#undef timeval
#undef timeval
typedef int sock_t;
#define INVALID_SOCKET (-1)
......@@ -667,6 +683,7 @@ extern "C" {
struct SlTimeval_t;
#define timeval SlTimeval_t
int gettimeofday(struct timeval *t, void *tz);
int settimeofday(const struct timeval *tv, const void *tz);
int asprintf(char **strp, const char *fmt, ...);
......@@ -690,7 +707,7 @@ struct stat {
};
int _stat(const char *pathname, struct stat *st);
#define stat(a, b) _stat(a, b)
int stat(const char *pathname, struct stat *st);
#define __S_IFMT 0170000
......@@ -706,8 +723,10 @@ int _stat(const char *pathname, struct stat *st);
#define S_ISDIR(mode) __S_ISTYPE((mode), __S_IFDIR)
#define S_ISREG(mode) __S_ISTYPE((mode), __S_IFREG)
/* As of 5.2.7, TI compiler does not support va_copy() yet. */
/* 5.x series compilers don't have va_copy, 16.x do. */
#if __TI_COMPILER_VERSION__ < 16000000
#define va_copy(apc, ap) ((apc) = (ap))
#endif
#endif /* __TI_COMPILER_VERSION__ */
......@@ -828,7 +847,8 @@ int _stat(const char *pathname, struct stat *st);
#define CS_ENABLE_STDIO 1
#endif
#if (defined(CC3200_FS_SPIFFS) || defined(CC3200_FS_SLFS)) && !defined(MG_ENABLE_FILESYSTEM)
#if (defined(CC3200_FS_SPIFFS) || defined(CC3200_FS_SLFS)) && \
!defined(MG_ENABLE_FILESYSTEM)
#define MG_ENABLE_FILESYSTEM 1
#endif
......@@ -872,15 +892,15 @@ typedef struct stat cs_stat_t;
#define __cdecl
#ifndef MG_NET_IF
# include <lwip/opt.h>
# if LWIP_SOCKET
# define MG_NET_IF MG_NET_IF_SOCKET
# else
# define MG_NET_IF MG_NET_IF_LWIP_LOW_LEVEL
# endif
# define MG_LWIP 1
#include <lwip/opt.h>
#if LWIP_SOCKET
#define MG_NET_IF MG_NET_IF_SOCKET
#else
#define MG_NET_IF MG_NET_IF_LWIP_LOW_LEVEL
#endif
#define MG_LWIP 1
#elif MG_NET_IF == MG_NET_IF_SIMPLELINK
# include "common/platforms/simplelink/cs_simplelink.h"
/* Amalgamated: #include "common/platforms/simplelink/cs_simplelink.h" */
#endif
#ifndef CS_ENABLE_STDIO
......@@ -1002,16 +1022,16 @@ in_addr_t inet_addr(const char *cp);
#define to64(x) strtoll(x, NULL, 10)
#define MG_NET_IF MG_NET_IF_LWIP_LOW_LEVEL
#define MG_LWIP 1
#define MG_ENABLE_IPV6 1
#define MG_NET_IF MG_NET_IF_LWIP_LOW_LEVEL
#define MG_LWIP 1
#define MG_ENABLE_IPV6 1
/*
* For ARM C Compiler, make lwip to export `struct timeval`; for other
* compilers, suppress it.
*/
#if !defined(__ARMCC_VERSION)
# define LWIP_TIMEVAL_PRIVATE 0
#define LWIP_TIMEVAL_PRIVATE 0
#else
struct timeval;
int gettimeofday(struct timeval *tp, void *tzp);
......@@ -1048,12 +1068,12 @@ int gettimeofday(struct timeval *tp, void *tzp);
#define to64(x) strtoll(x, NULL, 10)
#define MG_NET_IF MG_NET_IF_LWIP_LOW_LEVEL
#define MG_LWIP 1
#define MG_ENABLE_IPV6 1
#define MG_NET_IF MG_NET_IF_LWIP_LOW_LEVEL
#define MG_LWIP 1
#define MG_ENABLE_IPV6 1
#if !defined(ENOSPC)
# define ENOSPC 28 /* No space left on device */
#define ENOSPC 28 /* No space left on device */
#endif
/*
......@@ -1061,7 +1081,7 @@ int gettimeofday(struct timeval *tp, void *tzp);
* compilers, suppress it.
*/
#if !defined(__ARMCC_VERSION)
# define LWIP_TIMEVAL_PRIVATE 0
#define LWIP_TIMEVAL_PRIVATE 0
#endif
#define INT64_FMT PRId64
......@@ -1085,9 +1105,10 @@ int gettimeofday(struct timeval *tp, void *tzp);
#ifndef CS_COMMON_PLATFORMS_SIMPLELINK_CS_SIMPLELINK_H_
#define CS_COMMON_PLATFORMS_SIMPLELINK_CS_SIMPLELINK_H_
#if defined(MG_NET_IF) && MG_NET_IF == MG_NET_IF_SIMPLELINK
/* If simplelink.h is already included, all bets are off. */
#if defined(MG_NET_IF) && MG_NET_IF == MG_NET_IF_SIMPLELINK && \
!defined(__SIMPLELINK_H__)
#if !defined(__SIMPLELINK_H__)
#include <stdbool.h>
......@@ -1101,6 +1122,12 @@ int gettimeofday(struct timeval *tp, void *tzp);
#undef fd_set
#endif
#if CS_PLATFORM == CS_P_CC3220
#include <ti/drivers/net/wifi/porting/user.h>
#include <ti/drivers/net/wifi/simplelink.h>
#include <ti/drivers/net/wifi/sl_socket.h>
#include <ti/drivers/net/wifi/netapp.h>
#else
/* We want to disable SL_INC_STD_BSD_API_NAMING, so we include user.h ourselves
* and undef it. */
#define PROVISIONING_API_H_
......@@ -1110,6 +1137,7 @@ int gettimeofday(struct timeval *tp, void *tzp);
#include <simplelink/include/simplelink.h>
#include <simplelink/include/netapp.h>
#endif /* CS_PLATFORM == CS_P_CC3220 */
/* Now define only the subset of the BSD API that we use.
* Notably, close(), read() and write() are not defined. */
......@@ -1178,7 +1206,59 @@ int sl_set_ssl_opts(struct mg_connection *nc);
}
#endif
#endif /* MG_NET_IF == MG_NET_IF_SIMPLELINK && !defined(__SIMPLELINK_H__) */
#endif /* !defined(__SIMPLELINK_H__) */
/* Compatibility with older versions of SimpleLink */
#if SL_MAJOR_VERSION_NUM < 2
#define SL_ERROR_BSD_EAGAIN SL_EAGAIN
#define SL_ERROR_BSD_EALREADY SL_EALREADY
#define SL_ERROR_BSD_ENOPROTOOPT SL_ENOPROTOOPT
#define SL_ERROR_BSD_ESECDATEERROR SL_ESECDATEERROR
#define SL_ERROR_BSD_ESECSNOVERIFY SL_ESECSNOVERIFY
#define SL_ERROR_FS_FAILED_TO_ALLOCATE_MEM SL_FS_ERR_FAILED_TO_ALLOCATE_MEM
#define SL_ERROR_FS_FILE_HAS_NOT_BEEN_CLOSE_CORRECTLY \
SL_FS_FILE_HAS_NOT_BEEN_CLOSE_CORRECTLY
#define SL_ERROR_FS_FILE_NAME_EXIST SL_FS_FILE_NAME_EXIST
#define SL_ERROR_FS_FILE_NOT_EXISTS SL_FS_ERR_FILE_NOT_EXISTS
#define SL_ERROR_FS_NO_AVAILABLE_NV_INDEX SL_FS_ERR_NO_AVAILABLE_NV_INDEX
#define SL_ERROR_FS_NOT_ENOUGH_STORAGE_SPACE SL_FS_ERR_NO_AVAILABLE_BLOCKS
#define SL_ERROR_FS_NOT_SUPPORTED SL_FS_ERR_NOT_SUPPORTED
#define SL_ERROR_FS_WRONG_FILE_NAME SL_FS_WRONG_FILE_NAME
#define SL_ERROR_FS_INVALID_HANDLE SL_FS_ERR_INVALID_HANDLE
#define SL_NETCFG_MAC_ADDRESS_GET SL_MAC_ADDRESS_GET
#define SL_SOCKET_FD_ZERO SL_FD_ZERO
#define SL_SOCKET_FD_SET SL_FD_SET
#define SL_SOCKET_FD_ISSET SL_FD_ISSET
#define SL_SO_SECURE_DOMAIN_NAME_VERIFICATION SO_SECURE_DOMAIN_NAME_VERIFICATION
#define SL_FS_READ FS_MODE_OPEN_READ
#define SL_FS_WRITE FS_MODE_OPEN_WRITE
#define SL_FI_FILE_SIZE(fi) ((fi).FileLen)
#define SL_FI_FILE_MAX_SIZE(fi) ((fi).AllocatedLen)
#define SlDeviceVersion_t SlVersionFull
#define sl_DeviceGet sl_DevGet
#define SL_DEVICE_GENERAL SL_DEVICE_GENERAL_CONFIGURATION
#define SL_LEN_TYPE _u8
#define SL_OPT_TYPE _u8
#else /* SL_MAJOR_VERSION_NUM >= 2 */
#define FS_MODE_OPEN_CREATE(max_size, flag) \
(SL_FS_CREATE | SL_FS_CREATE_MAX_SIZE(max_size))
#define SL_FI_FILE_SIZE(fi) ((fi).Len)
#define SL_FI_FILE_MAX_SIZE(fi) ((fi).MaxSize)
#define SL_LEN_TYPE _u16
#define SL_OPT_TYPE _u16
#endif /* SL_MAJOR_VERSION_NUM < 2 */
int slfs_open(const unsigned char *fname, uint32_t flags);
#endif /* MG_NET_IF == MG_NET_IF_SIMPLELINK */
#endif /* CS_COMMON_PLATFORMS_SIMPLELINK_CS_SIMPLELINK_H_ */
#ifdef MG_MODULE_LINES
......@@ -1235,6 +1315,10 @@ int sl_set_ssl_opts(struct mg_connection *nc);
#define EWOULDBLOCK WSAEWOULDBLOCK
#endif
#ifndef EAGAIN
#define EAGAIN EWOULDBLOCK
#endif
#ifndef __func__
#define STRX(x) #x
#define STR(x) STRX(x)
......@@ -1361,18 +1445,18 @@ typedef struct _stati64 {
#endif
#ifndef _UINTPTR_T_DEFINED
typedef unsigned int* uintptr_t;
typedef unsigned int *uintptr_t;
#endif
#define _S_IFREG 2
#define _S_IFDIR 4
#ifndef S_ISDIR
#define S_ISDIR(x) (((x) & _S_IFDIR) != 0)
#define S_ISDIR(x) (((x) &_S_IFDIR) != 0)
#endif
#ifndef S_ISREG
#define S_ISREG(x) (((x) & _S_IFREG) != 0)
#define S_ISREG(x) (((x) &_S_IFREG) != 0)
#endif
int open(const char *filename, int oflag, int pmode);
......@@ -1409,7 +1493,8 @@ typedef struct stat cs_stat_t;
#define MG_NET_IF MG_NET_IF_LWIP_LOW_LEVEL
/*
* LPCXpress comes with 3 C library implementations: Newlib, NewlibNano and Redlib.
* LPCXpress comes with 3 C library implementations: Newlib, NewlibNano and
*Redlib.
* See https://community.nxp.com/message/630860 for more details.
*
* Redlib is the default and lacks certain things, so we provide them.
......@@ -1505,7 +1590,7 @@ typedef TCP_SOCKET sock_t;
#define CS_ENABLE_STDIO 1
#endif
char* inet_ntoa(struct in_addr in);
char *inet_ntoa(struct in_addr in);
#endif /* CS_PLATFORM == CS_P_PIC32 */
......@@ -1624,6 +1709,84 @@ void mg_lwip_set_keepalive_params(struct mg_connection *nc, int idle,
#endif /* CS_COMMON_PLATFORMS_LWIP_MG_LWIP_H_ */
#ifdef MG_MODULE_LINES
#line 1 "common/cs_md5.h"
#endif
/*
* Copyright (c) 2014 Cesanta Software Limited
* All rights reserved
*/
#ifndef CS_COMMON_MD5_H_
#define CS_COMMON_MD5_H_
/* Amalgamated: #include "common/platform.h" */
#ifndef CS_DISABLE_MD5
#define CS_DISABLE_MD5 0
#endif
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
typedef struct {
uint32_t buf[4];
uint32_t bits[2];
unsigned char in[64];
} cs_md5_ctx;
void cs_md5_init(cs_md5_ctx *c);
void cs_md5_update(cs_md5_ctx *c, const unsigned char *data, size_t len);
void cs_md5_final(unsigned char *md, cs_md5_ctx *c);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* CS_COMMON_MD5_H_ */
#ifdef MG_MODULE_LINES
#line 1 "common/cs_sha1.h"
#endif
/*
* Copyright (c) 2014 Cesanta Software Limited
* All rights reserved
*/
#ifndef CS_COMMON_SHA1_H_
#define CS_COMMON_SHA1_H_
#ifndef CS_DISABLE_SHA1
#define CS_DISABLE_SHA1 0
#endif
#if !CS_DISABLE_SHA1
/* Amalgamated: #include "common/platform.h" */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
typedef struct {
uint32_t state[5];
uint32_t count[2];
unsigned char buffer[64];
} cs_sha1_ctx;
void cs_sha1_init(cs_sha1_ctx *);
void cs_sha1_update(cs_sha1_ctx *, const unsigned char *data, uint32_t len);
void cs_sha1_final(unsigned char digest[20], cs_sha1_ctx *);
void cs_hmac_sha1(const unsigned char *key, size_t key_len,
const unsigned char *text, size_t text_len,
unsigned char out[20]);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* CS_DISABLE_SHA1 */
#endif /* CS_COMMON_SHA1_H_ */
#ifdef MG_MODULE_LINES
#line 1 "common/cs_time.h"
#endif
/*
......@@ -1634,6 +1797,8 @@ void mg_lwip_set_keepalive_params(struct mg_connection *nc, int idle,
#ifndef CS_COMMON_CS_TIME_H_
#define CS_COMMON_CS_TIME_H_
#include <time.h>
/* Amalgamated: #include "common/platform.h" */
#ifdef __cplusplus
......@@ -1643,6 +1808,12 @@ extern "C" {
/* Sub-second granularity time(). */
double cs_time(void);
/*
* Similar to (non-standard) timegm, converts broken-down time into the number
* of seconds since Unix Epoch.
*/
double cs_timegm(const struct tm *tm);
#ifdef __cplusplus
}
#endif /* __cplusplus */
......@@ -1665,7 +1836,7 @@ double cs_time(void);
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif
/* Describes chunk of memory */
struct mg_str {
......@@ -1683,6 +1854,8 @@ struct mg_str mg_mk_str_n(const char *s, size_t len);
/* Macro for initializing mg_str. */
#define MG_MK_STR(str_literal) \
{ str_literal, sizeof(str_literal) - 1 }
#define MG_NULL_STR \
{ NULL, 0 }
/*
* Cross-platform version of `strcmp()` where where first string is
......@@ -1696,13 +1869,28 @@ int mg_vcmp(const struct mg_str *str2, const char *str1);
*/
int mg_vcasecmp(const struct mg_str *str2, const char *str1);
/* Creates a copy of s (heap-allocated). */
struct mg_str mg_strdup(const struct mg_str s);
/*
* Creates a copy of s (heap-allocated).
* Resulting string is NUL-terminated (but NUL is not included in len).
*/
struct mg_str mg_strdup_nul(const struct mg_str s);
/*
* Locates character in a string.
*/
const char *mg_strchr(const struct mg_str s, int c);
int mg_strcmp(const struct mg_str str1, const struct mg_str str2);
int mg_strncmp(const struct mg_str str1, const struct mg_str str2, size_t n);
const char *mg_strstr(const struct mg_str haystack, const struct mg_str needle);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
#endif /* CS_COMMON_MG_STR_H_ */
#ifdef MG_MODULE_LINES
......@@ -1788,94 +1976,6 @@ void mbuf_trim(struct mbuf *);
#endif /* CS_COMMON_MBUF_H_ */
#ifdef MG_MODULE_LINES
#line 1 "common/sha1.h"
#endif
/*
* Copyright (c) 2014 Cesanta Software Limited
* All rights reserved
*/
#ifndef CS_COMMON_SHA1_H_
#define CS_COMMON_SHA1_H_
#ifndef DISABLE_SHA1
#define DISABLE_SHA1 0
#endif
#if !DISABLE_SHA1
/* Amalgamated: #include "common/platform.h" */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
typedef struct {
uint32_t state[5];
uint32_t count[2];
unsigned char buffer[64];
} cs_sha1_ctx;
void cs_sha1_init(cs_sha1_ctx *);
void cs_sha1_update(cs_sha1_ctx *, const unsigned char *data, uint32_t len);
void cs_sha1_final(unsigned char digest[20], cs_sha1_ctx *);
void cs_hmac_sha1(const unsigned char *key, size_t key_len,
const unsigned char *text, size_t text_len,
unsigned char out[20]);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* DISABLE_SHA1 */
#endif /* CS_COMMON_SHA1_H_ */
#ifdef MG_MODULE_LINES
#line 1 "common/md5.h"
#endif
/*
* Copyright (c) 2014 Cesanta Software Limited
* All rights reserved
*/
#ifndef CS_COMMON_MD5_H_
#define CS_COMMON_MD5_H_
/* Amalgamated: #include "common/platform.h" */
#ifndef DISABLE_MD5
#define DISABLE_MD5 0
#endif
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
typedef struct MD5Context {
uint32_t buf[4];
uint32_t bits[2];
unsigned char in[64];
} MD5_CTX;
void MD5_Init(MD5_CTX *c);
void MD5_Update(MD5_CTX *c, const unsigned char *data, size_t len);
void MD5_Final(unsigned char *md, MD5_CTX *c);
/*
* Return stringified MD5 hash for NULL terminated list of pointer/length pairs.
* A length should be specified as size_t variable.
* Example:
*
* char buf[33];
* cs_md5(buf, "foo", (size_t) 3, "bar", (size_t) 3, NULL);
*/
char *cs_md5(char buf[33], ...);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* CS_COMMON_MD5_H_ */
#ifdef MG_MODULE_LINES
#line 1 "common/base64.h"
#endif
/*
......@@ -1939,6 +2039,7 @@ int cs_base64_decode(const unsigned char *s, int len, char *dst, int *dec_len);
#include <stdlib.h>
/* Amalgamated: #include "common/platform.h" */
/* Amalgamated: #include "common/mg_str.h" */
#ifndef CS_ENABLE_STRDUP
#define CS_ENABLE_STRDUP 0
......@@ -2033,6 +2134,34 @@ int mg_asprintf(char **buf, size_t size, const char *fmt, ...);
/* Same as mg_asprintf, but takes varargs list. */
int mg_avprintf(char **buf, size_t size, const char *fmt, va_list ap);
/*
* A helper function for traversing a comma separated list of values.
* It returns a list pointer shifted to the next value or NULL if the end
* of the list found.
* The value is stored in a val vector. If the value has a form "x=y", then
* eq_val vector is initialised to point to the "y" part, and val vector length
* is adjusted to point only to "x".
* If the list is just a comma separated list of entries, like "aa,bb,cc" then
* `eq_val` will contain zero-length string.
*
* The purpose of this function is to parse comma separated string without
* any copying/memory allocation.
*/
const char *mg_next_comma_list_entry(const char *list, struct mg_str *val,
struct mg_str *eq_val);
struct mg_str mg_next_comma_list_entry_n(struct mg_str list, struct mg_str *val,
struct mg_str *eq_val);
/*
* Matches 0-terminated string (mg_match_prefix) or string with given length
* mg_match_prefix_n against a glob pattern.
*
* Match is case-insensitive. Returns number of bytes matched, or -1 if no
* match.
*/
int mg_match_prefix(const char *pattern, int pattern_len, const char *str);
int mg_match_prefix_n(const struct mg_str pattern, const struct mg_str str);
#ifdef __cplusplus
}
#endif
......@@ -2896,10 +3025,6 @@ struct { \
#define MG_ENABLE_IPV6 0
#endif
#ifndef MG_ENABLE_JAVASCRIPT
#define MG_ENABLE_JAVASCRIPT 0
#endif
#ifndef MG_ENABLE_MQTT
#define MG_ENABLE_MQTT 1
#endif
......@@ -2963,6 +3088,18 @@ struct { \
#define MG_ENABLE_EXTRA_ERRORS_DESC 0
#endif
#ifndef MG_ENABLE_CALLBACK_USERDATA
#define MG_ENABLE_CALLBACK_USERDATA 0
#endif
#if MG_ENABLE_CALLBACK_USERDATA
#define MG_UD_ARG(ud) , ud
#define MG_CB(cb, ud) cb, ud
#else
#define MG_UD_ARG(ud)
#define MG_CB(cb, ud) cb
#endif
#endif /* CS_MONGOOSE_SRC_FEATURES_H_ */
#ifdef MG_MODULE_LINES
#line 1 "mongoose/src/net_if.h"
......@@ -3002,7 +3139,7 @@ struct mg_iface_vtable;
struct mg_iface {
struct mg_mgr *mgr;
void *data; /* Implementation-specific data */
struct mg_iface_vtable *vtable;
const struct mg_iface_vtable *vtable;
};
struct mg_iface_vtable {
......@@ -3041,11 +3178,11 @@ struct mg_iface_vtable {
union socket_address *sa);
};
extern struct mg_iface_vtable *mg_ifaces[];
extern const struct mg_iface_vtable *mg_ifaces[];
extern int mg_num_ifaces;
/* Creates a new interface instance. */
struct mg_iface *mg_if_create_iface(struct mg_iface_vtable *vtable,
struct mg_iface *mg_if_create_iface(const struct mg_iface_vtable *vtable,
struct mg_mgr *mgr);
/*
......@@ -3053,7 +3190,7 @@ struct mg_iface *mg_if_create_iface(struct mg_iface_vtable *vtable,
* interface `from`, exclusive. Returns NULL if none is found.
*/
struct mg_iface *mg_find_iface(struct mg_mgr *mgr,
struct mg_iface_vtable *vtable,
const struct mg_iface_vtable *vtable,
struct mg_iface *from);
/*
* Deliver a new TCP connection. Returns NULL in case on error (unable to
......@@ -3141,6 +3278,7 @@ enum mg_ssl_if_result mg_ssl_if_conn_init(
const char **err_msg);
enum mg_ssl_if_result mg_ssl_if_conn_accept(struct mg_connection *nc,
struct mg_connection *lc);
void mg_ssl_if_conn_close_notify(struct mg_connection *nc);
void mg_ssl_if_conn_free(struct mg_connection *nc);
enum mg_ssl_if_result mg_ssl_if_handshake(struct mg_connection *nc);
......@@ -3187,11 +3325,6 @@ int mg_ssl_if_write(struct mg_connection *nc, const void *data, size_t len);
#ifndef CS_MONGOOSE_SRC_NET_H_
#define CS_MONGOOSE_SRC_NET_H_
#if MG_ENABLE_JAVASCRIPT
#define EXCLUDE_COMMON
#include <v7.h>
#endif
/* Amalgamated: #include "mongoose/src/common.h" */
/* Amalgamated: #include "mongoose/src/net_if.h" */
/* Amalgamated: #include "common/mbuf.h" */
......@@ -3229,13 +3362,13 @@ struct mg_connection;
* Mongoose calls the event handler, passing the events defined below.
*/
typedef void (*mg_event_handler_t)(struct mg_connection *nc, int ev,
void *ev_data);
void *ev_data MG_UD_ARG(void *user_data));
/* Events. Meaning of event parameter (evp) is given in the comment. */
#define MG_EV_POLL 0 /* Sent to each connection on each mg_mgr_poll() call */
#define MG_EV_ACCEPT 1 /* New connection accepted. union socket_address * */
#define MG_EV_CONNECT 2 /* connect() succeeded or failed. int * */
#define MG_EV_RECV 3 /* Data has benn received. int *num_bytes */
#define MG_EV_RECV 3 /* Data has been received. int *num_bytes */
#define MG_EV_SEND 4 /* Data has been written to a socket. int *num_bytes */
#define MG_EV_CLOSE 5 /* Connection is closed. NULL */
#define MG_EV_TIMER 6 /* now >= conn->ev_timer_time. double * */
......@@ -3254,9 +3387,7 @@ struct mg_mgr {
void *user_data; /* User data */
int num_ifaces;
struct mg_iface **ifaces; /* network interfaces */
#if MG_ENABLE_JAVASCRIPT
struct v7 *v7;
#endif
const char *nameserver; /* DNS server to use */
};
/*
......@@ -3348,9 +3479,10 @@ void mg_mgr_init(struct mg_mgr *mgr, void *user_data);
* `num_ifaces` pointers it contains will be reclaimed by `mg_mgr_free`.
*/
struct mg_mgr_init_opts {
struct mg_iface_vtable *main_iface;
const struct mg_iface_vtable *main_iface;
int num_ifaces;
struct mg_iface_vtable **ifaces;
const struct mg_iface_vtable **ifaces;
const char *nameserver;
};
/*
......@@ -3392,7 +3524,8 @@ time_t mg_mgr_poll(struct mg_mgr *, int milli);
* be passed as the `ev_data` pointer. Maximum message size is capped
* by `MG_CTL_MSG_MESSAGE_SIZE` which is set to 8192 bytes.
*/
void mg_broadcast(struct mg_mgr *, mg_event_handler_t func, void *, size_t);
void mg_broadcast(struct mg_mgr *mgr, mg_event_handler_t cb, void *data,
size_t len);
#endif
/*
......@@ -3408,7 +3541,7 @@ void mg_broadcast(struct mg_mgr *, mg_event_handler_t func, void *, size_t);
* }
* ```
*/
struct mg_connection *mg_next(struct mg_mgr *, struct mg_connection *);
struct mg_connection *mg_next(struct mg_mgr *mgr, struct mg_connection *c);
/*
* Optional parameters to `mg_add_sock_opt()`.
......@@ -3429,7 +3562,9 @@ struct mg_add_sock_opts {
*
* For more options see the `mg_add_sock_opt` variant.
*/
struct mg_connection *mg_add_sock(struct mg_mgr *, sock_t, mg_event_handler_t);
struct mg_connection *mg_add_sock(struct mg_mgr *mgr, sock_t sock,
MG_CB(mg_event_handler_t handler,
void *user_data));
/*
* Creates a connection, associates it with the given socket and event handler
......@@ -3437,9 +3572,10 @@ struct mg_connection *mg_add_sock(struct mg_mgr *, sock_t, mg_event_handler_t);
*
* See the `mg_add_sock_opts` structure for a description of the options.
*/
struct mg_connection *mg_add_sock_opt(struct mg_mgr *, sock_t,
mg_event_handler_t,
struct mg_add_sock_opts);
struct mg_connection *mg_add_sock_opt(struct mg_mgr *mgr, sock_t sock,
MG_CB(mg_event_handler_t handler,
void *user_data),
struct mg_add_sock_opts opts);
/*
* Optional parameters to `mg_bind_opt()`.
......@@ -3485,8 +3621,9 @@ struct mg_bind_opts {
*
* See `mg_bind_opt` for full documentation.
*/
struct mg_connection *mg_bind(struct mg_mgr *, const char *,
mg_event_handler_t);
struct mg_connection *mg_bind(struct mg_mgr *mgr, const char *address,
MG_CB(mg_event_handler_t handler,
void *user_data));
/*
* Creates a listening connection.
*
......@@ -3495,7 +3632,7 @@ struct mg_connection *mg_bind(struct mg_mgr *, const char *,
* `address` can be just a port number, e.g. `:8000`. To bind to a specific
* interface, an IP address can be specified, e.g. `1.2.3.4:8000`. By default,
* a TCP connection is created. To create UDP connection, prepend `udp://`
* prefix, e.g. `udp://:8000`. To summarize, `address` paramer has following
* prefix, e.g. `udp://:8000`. To summarize, `address` parameter has following
* format: `[PROTO://][IP_ADDRESS]:PORT`, where `PROTO` could be `tcp` or
* `udp`.
*
......@@ -3506,7 +3643,8 @@ struct mg_connection *mg_bind(struct mg_mgr *, const char *,
* NOTE: The connection remains owned by the manager, do not free().
*/
struct mg_connection *mg_bind_opt(struct mg_mgr *mgr, const char *address,
mg_event_handler_t handler,
MG_CB(mg_event_handler_t handler,
void *user_data),
struct mg_bind_opts opts);
/* Optional parameters to `mg_connect_opt()` */
......@@ -3515,6 +3653,7 @@ struct mg_connect_opts {
unsigned int flags; /* Extra connection flags */
const char **error_string; /* Placeholder for the error string */
struct mg_iface *iface; /* Interface instance */
const char *nameserver; /* DNS server to use, NULL for default */
#if MG_ENABLE_SSL
/*
* SSL settings.
......@@ -3569,7 +3708,8 @@ struct mg_connect_opts {
* See `mg_connect_opt()` for full documentation.
*/
struct mg_connection *mg_connect(struct mg_mgr *mgr, const char *address,
mg_event_handler_t handler);
MG_CB(mg_event_handler_t handler,
void *user_data));
/*
* Connects to a remote host.
......@@ -3620,7 +3760,8 @@ struct mg_connection *mg_connect(struct mg_mgr *mgr, const char *address,
* ```
*/
struct mg_connection *mg_connect_opt(struct mg_mgr *mgr, const char *address,
mg_event_handler_t handler,
MG_CB(mg_event_handler_t handler,
void *user_data),
struct mg_connect_opts opts);
#if MG_ENABLE_SSL && MG_NET_IF != MG_NET_IF_SIMPLELINK
......@@ -3701,7 +3842,7 @@ int mg_resolve(const char *domain_name, char *ip_addr_buf, size_t buf_len);
* is to allow all access. On each request the full list is traversed,
* and the last match wins. Example:
*
* `-0.0.0.0/0,+192.168/16` - deny all acccesses, only allow 192.168/16 subnet
* `-0.0.0.0/0,+192.168/16` - deny all accesses, only allow 192.168/16 subnet
*
* To learn more about subnet masks, see this
* link:https://en.wikipedia.org/wiki/Subnetwork[Wikipedia page on Subnetwork].
......@@ -3710,17 +3851,6 @@ int mg_resolve(const char *domain_name, char *ip_addr_buf, size_t buf_len);
*/
int mg_check_ip_acl(const char *acl, uint32_t remote_ip);
#if MG_ENABLE_JAVASCRIPT
/*
* Enables server-side JavaScript scripting.
* Requires a `-DMG_ENABLE_JAVASCRIPT` compilation flag and V7 engine sources.
* V7 instance must not be destroyed during manager's lifetime.
* Returns a V7 error.
*/
enum v7_err mg_enable_javascript(struct mg_mgr *m, struct v7 *v7,
const char *init_js_file_name);
#endif
/*
* Schedules an MG_EV_TIMER event to be delivered at `timestamp` time.
* `timestamp` is UNIX time (the number of seconds since Epoch). It is
......@@ -3801,11 +3931,26 @@ extern "C" {
*
* Returns 0 on success, -1 on error.
*/
int mg_parse_uri(struct mg_str uri, struct mg_str *scheme,
int mg_parse_uri(const struct mg_str uri, struct mg_str *scheme,
struct mg_str *user_info, struct mg_str *host,
unsigned int *port, struct mg_str *path, struct mg_str *query,
struct mg_str *fragment);
/*
* Assemble URI from parts. Any of the inputs can be NULL or zero-length mg_str.
*
* If normalize_path is true, path is normalized by resolving relative refs.
*
* Result is a heap-allocated string (uri->p must be free()d after use).
*
* Returns 0 on success, -1 on error.
*/
int mg_assemble_uri(const struct mg_str *scheme, const struct mg_str *user_info,
const struct mg_str *host, unsigned int port,
const struct mg_str *path, const struct mg_str *query,
const struct mg_str *fragment, int normalize_path,
struct mg_str *uri);
int mg_normalize_uri_path(const struct mg_str *in, struct mg_str *out);
#ifdef __cplusplus
......@@ -3836,8 +3981,12 @@ int mg_normalize_uri_path(const struct mg_str *in, struct mg_str *out);
extern "C" {
#endif /* __cplusplus */
#ifndef MAX_PATH_SIZE
#define MAX_PATH_SIZE 500
#ifndef MG_MAX_PATH
#ifdef PATH_MAX
#define MG_MAX_PATH PATH_MAX
#else
#define MG_MAX_PATH 256
#endif
#endif
/*
......@@ -3898,6 +4047,21 @@ FILE *mg_fopen(const char *path, const char *mode);
* Return value is the same as for the `open()` syscall.
*/
int mg_open(const char *path, int flag, int mode);
/*
* Reads data from the given file stream.
*
* Return value is a number of bytes readen.
*/
size_t mg_fread(void *ptr, size_t size, size_t count, FILE *f);
/*
* Writes data to the given file stream.
*
* Return value is a number of bytes wtitten.
*/
size_t mg_fwrite(const void *ptr, size_t size, size_t count, FILE *f);
#endif /* MG_ENABLE_FILESYSTEM */
#if MG_ENABLE_THREADS
......@@ -3927,9 +4091,10 @@ void mg_set_close_on_exec(sock_t);
*
* If both port number and IP address are printed, they are separated by `:`.
* If compiled with `-DMG_ENABLE_IPV6`, IPv6 addresses are supported.
* Return length of the stringified address.
*/
void mg_conn_addr_to_str(struct mg_connection *nc, char *buf, size_t len,
int flags);
int mg_conn_addr_to_str(struct mg_connection *c, char *buf, size_t len,
int flags);
#if MG_NET_IF == MG_NET_IF_SOCKET
/* Legacy interface. */
void mg_sock_to_str(sock_t sock, char *buf, size_t len, int flags);
......@@ -3940,8 +4105,8 @@ void mg_sock_to_str(sock_t sock, char *buf, size_t len, int flags);
*
* `flags` is MG_SOCK_STRINGIFY_IP and/or MG_SOCK_STRINGIFY_PORT.
*/
void mg_sock_addr_to_str(const union socket_address *sa, char *buf, size_t len,
int flags);
int mg_sock_addr_to_str(const union socket_address *sa, char *buf, size_t len,
int flags);
#if MG_ENABLE_HEXDUMP
/*
......@@ -3973,32 +4138,6 @@ void mg_hexdump_connection(struct mg_connection *nc, const char *path,
*/
int mg_is_big_endian(void);
/*
* A helper function for traversing a comma separated list of values.
* It returns a list pointer shifted to the next value or NULL if the end
* of the list found.
* The value is stored in a val vector. If the value has a form "x=y", then
* eq_val vector is initialised to point to the "y" part, and val vector length
* is adjusted to point only to "x".
* If the list is just a comma separated list of entries, like "aa,bb,cc" then
* `eq_val` will contain zero-length string.
*
* The purpose of this function is to parse comma separated string without
* any copying/memory allocation.
*/
const char *mg_next_comma_list_entry(const char *list, struct mg_str *val,
struct mg_str *eq_val);
/*
* Matches 0-terminated string (mg_match_prefix) or string with given length
* mg_match_prefix_n against a glob pattern.
*
* Match is case-insensitive. Returns number of bytes matched, or -1 if no
* match.
*/
int mg_match_prefix(const char *pattern, int pattern_len, const char *str);
int mg_match_prefix_n(const struct mg_str pattern, const struct mg_str str);
/*
* Use with cs_base64_init/update/finish in order to write out base64 in chunks.
*/
......@@ -4014,7 +4153,16 @@ void mg_mbuf_append_base64(struct mbuf *mbuf, const void *data, size_t len);
* If pass is NULL, then user is expected to contain the credentials pair
* already encoded as `user:pass`.
*/
void mg_basic_auth_header(const char *user, const char *pass, struct mbuf *buf);
void mg_basic_auth_header(const struct mg_str user, const struct mg_str pass,
struct mbuf *buf);
/*
* URL-escape the specified string.
* All non-printable characters are escaped, plus `._-$,;~()/`.
* Input need not be NUL-terminated, but the returned string is.
* Returned string is heap-allocated and must be free()'d.
*/
struct mg_str mg_url_encode(const struct mg_str src);
#ifdef __cplusplus
}
......@@ -4052,14 +4200,6 @@ extern "C" {
#define MG_MAX_HTTP_REQUEST_SIZE 1024
#endif
#ifndef MG_MAX_PATH
#ifdef PATH_MAX
#define MG_MAX_PATH PATH_MAX
#else
#define MG_MAX_PATH 256
#endif
#endif
#ifndef MG_MAX_HTTP_SEND_MBUF
#define MG_MAX_HTTP_SEND_MBUF 1024
#endif
......@@ -4071,6 +4211,7 @@ extern "C" {
/* HTTP message */
struct http_message {
struct mg_str message; /* Whole message: request line + headers + body */
struct mg_str body; /* Message body. 0-length for requests with no body */
/* HTTP Request line (or HTTP response line) */
struct mg_str method; /* "GET" */
......@@ -4094,9 +4235,6 @@ struct http_message {
/* Headers */
struct mg_str header_names[MG_MAX_HTTP_HEADERS];
struct mg_str header_values[MG_MAX_HTTP_HEADERS];
/* Message body */
struct mg_str body; /* Zero-length for requests with no body */
};
#if MG_ENABLE_HTTP_WEBSOCKET
......@@ -4238,6 +4376,17 @@ void mg_send_websocket_handshake3(struct mg_connection *nc, const char *path,
const char *host, const char *protocol,
const char *extra_headers, const char *user,
const char *pass);
/* Same as mg_send_websocket_handshake3 but with strings not necessarily
* NUL-temrinated */
void mg_send_websocket_handshake3v(struct mg_connection *nc,
const struct mg_str path,
const struct mg_str host,
const struct mg_str protocol,
const struct mg_str extra_headers,
const struct mg_str user,
const struct mg_str pass);
/*
* Helper function that creates an outbound WebSocket connection.
*
......@@ -4259,7 +4408,8 @@ void mg_send_websocket_handshake3(struct mg_connection *nc, const char *path,
* ```
*/
struct mg_connection *mg_connect_ws(struct mg_mgr *mgr,
mg_event_handler_t event_handler,
MG_CB(mg_event_handler_t event_handler,
void *user_data),
const char *url, const char *protocol,
const char *extra_headers);
......@@ -4269,11 +4419,10 @@ struct mg_connection *mg_connect_ws(struct mg_mgr *mgr,
* Mostly identical to `mg_connect_ws`, but allows to provide extra parameters
* (for example, SSL parameters)
*/
struct mg_connection *mg_connect_ws_opt(struct mg_mgr *mgr,
mg_event_handler_t ev_handler,
struct mg_connect_opts opts,
const char *url, const char *protocol,
const char *extra_headers);
struct mg_connection *mg_connect_ws_opt(
struct mg_mgr *mgr, MG_CB(mg_event_handler_t ev_handler, void *user_data),
struct mg_connect_opts opts, const char *url, const char *protocol,
const char *extra_headers);
/*
* Send WebSocket frame to the remote end.
......@@ -4299,7 +4448,8 @@ void mg_send_websocket_frame(struct mg_connection *nc, int op_and_flags,
/*
* Sends multiple websocket frames.
*
* Like `mg_send_websocket_frame()`, but composes a frame from multiple buffers.
* Like `mg_send_websocket_frame()`, but composes a frame from multiple
*buffers.
*/
void mg_send_websocket_framev(struct mg_connection *nc, int op_and_flags,
const struct mg_str *strings, int num_strings);
......@@ -4344,12 +4494,18 @@ void mg_printf_websocket_frame(struct mg_connection *nc, int op_and_flags,
* (`dst`, `dst_len`). If `is_form_url_encoded` is non-zero, then
* `+` character is decoded as a blank space character. This function
* guarantees to NUL-terminate the destination. If destination is too small,
* then the source string is partially decoded and `-1` is returned. Otherwise,
* then the source string is partially decoded and `-1` is returned.
*Otherwise,
* a length of the decoded string is returned, not counting final NUL.
*/
int mg_url_decode(const char *src, int src_len, char *dst, int dst_len,
int is_form_url_encoded);
extern void mg_hash_md5_v(size_t num_msgs, const uint8_t *msgs[],
const size_t *msg_lens, uint8_t *digest);
extern void mg_hash_sha1_v(size_t num_msgs, const uint8_t *msgs[],
const size_t *msg_lens, uint8_t *digest);
#ifdef __cplusplus
}
#endif /* __cplusplus */
......@@ -4473,7 +4629,8 @@ size_t mg_parse_multipart(const char *buf, size_t buf_len, char *var_name,
* Fetches a variable `name` from a `buf` into a buffer specified by `dst`,
* `dst_len`. The destination is always zero-terminated. Returns the length of
* a fetched variable. If not found, 0 is returned. `buf` must be valid
* url-encoded buffer. If destination is too small, `-1` is returned.
* url-encoded buffer. If destination is too small or an error occured,
* negative number is returned.
*/
int mg_get_http_var(const struct mg_str *buf, const char *name, char *dst,
size_t dst_len);
......@@ -4724,7 +4881,8 @@ typedef struct mg_str (*mg_fu_fname_fn)(struct mg_connection *nc,
* ```
*/
void mg_file_upload_handler(struct mg_connection *nc, int ev, void *ev_data,
mg_fu_fname_fn local_name_fn);
mg_fu_fname_fn local_name_fn
MG_UD_ARG(void *user_data));
#endif /* MG_ENABLE_HTTP_STREAMING_MULTIPART */
#endif /* MG_ENABLE_FILESYSTEM */
......@@ -4742,7 +4900,7 @@ void mg_file_upload_handler(struct mg_connection *nc, int ev, void *ev_data,
* nc->flags |= MG_F_SEND_AND_CLOSE;
* }
*
* static void handle_hello1(struct mg_connection *nc, int ev, void *ev_data) {
* static void handle_hello2(struct mg_connection *nc, int ev, void *ev_data) {
* (void) ev; (void) ev_data;
* mg_printf(nc, "HTTP/1.0 200 OK\r\n\r\n[I am Hello2]");
* nc->flags |= MG_F_SEND_AND_CLOSE;
......@@ -4756,7 +4914,20 @@ void mg_file_upload_handler(struct mg_connection *nc, int ev, void *ev_data,
* ```
*/
void mg_register_http_endpoint(struct mg_connection *nc, const char *uri_path,
mg_event_handler_t handler);
MG_CB(mg_event_handler_t handler,
void *user_data));
struct mg_http_endpoint_opts {
void *user_data;
/* Authorization domain (realm) */
const char *auth_domain;
const char *auth_file;
};
void mg_register_http_endpoint_opt(struct mg_connection *nc,
const char *uri_path,
mg_event_handler_t handler,
struct mg_http_endpoint_opts opts);
/*
* Authenticates a HTTP request against an opened password file.
......@@ -4765,11 +4936,23 @@ void mg_register_http_endpoint(struct mg_connection *nc, const char *uri_path,
int mg_http_check_digest_auth(struct http_message *hm, const char *auth_domain,
FILE *fp);
/*
* Authenticates given response params against an opened password file.
* Returns 1 if authenticated, 0 otherwise.
*
* It's used by mg_http_check_digest_auth().
*/
int mg_check_digest_auth(struct mg_str method, struct mg_str uri,
struct mg_str username, struct mg_str cnonce,
struct mg_str response, struct mg_str qop,
struct mg_str nc, struct mg_str nonce,
struct mg_str auth_domain, FILE *fp);
/*
* Sends buffer `buf` of size `len` to the client using chunked HTTP encoding.
* This function sends the buffer size as hex number + newline first, then
* the buffer itself, then the newline. For example,
* `mg_send_http_chunk(nc, "foo", 3)` whill append the `3\r\nfoo\r\n` string
* `mg_send_http_chunk(nc, "foo", 3)` will append the `3\r\nfoo\r\n` string
* to the `nc->send_mbuf` output IO buffer.
*
* NOTE: The HTTP header "Transfer-Encoding: chunked" should be sent prior to
......@@ -4794,7 +4977,7 @@ void mg_printf_http_chunk(struct mg_connection *nc, const char *fmt, ...);
/*
* Sends the response status line.
* If `extra_headers` is not NULL, then `extra_headers` are also sent
* after the reponse line. `extra_headers` must NOT end end with new line.
* after the response line. `extra_headers` must NOT end end with new line.
* Example:
*
* mg_send_response_line(nc, 200, "Access-Control-Allow-Origin: *");
......@@ -4818,7 +5001,7 @@ void mg_http_send_error(struct mg_connection *nc, int code, const char *reason);
* `status_code` should be either 301 or 302 and `location` point to the
* new location.
* If `extra_headers` is not empty, then `extra_headers` are also sent
* after the reponse line. `extra_headers` must NOT end end with new line.
* after the response line. `extra_headers` must NOT end end with new line.
*
* Example:
*
......@@ -4911,11 +5094,10 @@ extern "C" {
* "var_1=value_1&var_2=value_2");
* ```
*/
struct mg_connection *mg_connect_http(struct mg_mgr *mgr,
mg_event_handler_t event_handler,
const char *url,
const char *extra_headers,
const char *post_data);
struct mg_connection *mg_connect_http(
struct mg_mgr *mgr,
MG_CB(mg_event_handler_t event_handler, void *user_data), const char *url,
const char *extra_headers, const char *post_data);
/*
* Helper function that creates an outbound HTTP connection.
......@@ -4924,12 +5106,10 @@ struct mg_connection *mg_connect_http(struct mg_mgr *mgr,
*parameters
* (for example, SSL parameters)
*/
struct mg_connection *mg_connect_http_opt(struct mg_mgr *mgr,
mg_event_handler_t ev_handler,
struct mg_connect_opts opts,
const char *url,
const char *extra_headers,
const char *post_data);
struct mg_connection *mg_connect_http_opt(
struct mg_mgr *mgr, MG_CB(mg_event_handler_t ev_handler, void *user_data),
struct mg_connect_opts opts, const char *url, const char *extra_headers,
const char *post_data);
/* Creates digest authentication header for a client request. */
int mg_http_create_digest_auth_header(char *buf, size_t buf_len,
......@@ -4973,6 +5153,7 @@ int mg_http_create_digest_auth_header(char *buf, size_t buf_len,
struct mg_mqtt_message {
int cmd;
int qos;
int len; /* message length in the IO buffer */
struct mg_str topic;
struct mg_str payload;
......@@ -5008,6 +5189,7 @@ struct mg_send_mqtt_handshake_opts {
/* mg_mqtt_proto_data should be in header to allow external access to it */
struct mg_mqtt_proto_data {
uint16_t keep_alive;
double last_control_time;
};
/* Message types */
......@@ -5152,6 +5334,19 @@ void mg_mqtt_pong(struct mg_connection *nc);
int mg_mqtt_next_subscribe_topic(struct mg_mqtt_message *msg,
struct mg_str *topic, uint8_t *qos, int pos);
/*
* Matches a topic against a topic expression
*
* Returns 1 if it matches; 0 otherwise.
*/
int mg_mqtt_match_topic_expression(struct mg_str exp, struct mg_str topic);
/*
* Same as `mg_mqtt_match_topic_expression()`, but takes `exp` as a
* NULL-terminated string.
*/
int mg_mqtt_vmatch_topic_expression(const char *exp, struct mg_str topic);
#ifdef __cplusplus
}
#endif /* __cplusplus */
......@@ -5193,7 +5388,9 @@ int mg_mqtt_next_subscribe_topic(struct mg_mqtt_message *msg,
extern "C" {
#endif /* __cplusplus */
#define MG_MQTT_MAX_SESSION_SUBSCRIPTIONS 512;
#ifndef MG_MQTT_MAX_SESSION_SUBSCRIPTIONS
#define MG_MQTT_MAX_SESSION_SUBSCRIPTIONS 512
#endif
struct mg_mqtt_broker;
......@@ -5290,6 +5487,8 @@ extern "C" {
#define MG_DNS_AAAA_RECORD 0x1c /* Lookup IPv6 address */
#define MG_DNS_SRV_RECORD 0x21 /* Lookup SRV */
#define MG_DNS_MX_RECORD 0x0f /* Lookup mail server for domain */
#define MG_DNS_ANY_RECORD 0xff
#define MG_DNS_NSEC_RECORD 0x2f
#define MG_MAX_DNS_QUESTIONS 32
#define MG_MAX_DNS_ANSWERS 32
......@@ -5379,7 +5578,7 @@ int mg_dns_copy_questions(struct mbuf *io, struct mg_dns_message *msg);
* struct because they might be invalidated as soon as the IO buffer grows
* again.
*
* Returns the number of bytes appened or -1 in case of error.
* Returns the number of bytes appended or -1 in case of error.
*/
int mg_dns_encode_record(struct mbuf *io, struct mg_dns_resource_record *rr,
const char *name, size_t nlen, const void *rdata,
......@@ -5557,7 +5756,7 @@ typedef void (*mg_resolve_callback_t)(struct mg_dns_message *dns_message,
/* Options for `mg_resolve_async_opt`. */
struct mg_resolve_async_opts {
const char *nameserver_url;
const char *nameserver;
int max_retries; /* defaults to 2 if zero */
int timeout; /* in seconds; defaults to 5 if zero */
int accept_literal; /* pseudo-resolve literal ipv4 and ipv6 addrs */
......@@ -5569,6 +5768,9 @@ struct mg_resolve_async_opts {
int mg_resolve_async(struct mg_mgr *mgr, const char *name, int query,
mg_resolve_callback_t cb, void *data);
/* Set default DNS server */
void mg_set_nameserver(struct mg_mgr *mgr, const char *nameserver);
/*
* Resolved a DNS name asynchronously.
*
......@@ -5717,7 +5919,7 @@ struct mg_coap_option *mg_coap_add_option(struct mg_coap_message *cm,
/*
* Frees the memory allocated for options.
* If the cm paramater doesn't contain any option it does nothing.
* If the cm parameter doesn't contain any option it does nothing.
*/
void mg_coap_free_options(struct mg_coap_message *cm);
......@@ -5809,7 +6011,8 @@ struct mg_sntp_message {
/* Establishes connection to given sntp server */
struct mg_connection *mg_sntp_connect(struct mg_mgr *mgr,
mg_event_handler_t event_handler,
MG_CB(mg_event_handler_t event_handler,
void *user_data),
const char *sntp_server_name);
/* Sends time request to given connection */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment