diff --git a/docs/README.md b/docs/README.md index 2861bf5e551d022f9d67fb9de7d74803fb46235b..1bee17131c4114e00b59a7382e17f2c2dbf8542e 100644 --- a/docs/README.md +++ b/docs/README.md @@ -10,26 +10,6 @@ by a 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. - -## Features - -* Works on Linux/UNIX, MacOS, Windows, QNX, eCos, Android and other -* Works on embedded hardware: STM32, ESP32, NXP, Xilinx, and other -* Built-in protocols: - - plain TCP, plain UDP, SSL/TLS (over TCP, one-way or two-way) - - HTTP client, HTTP server - - WebSocket client, WebSocket server - - MQTT client, MQTT server - - DNS client, async DNS resolver -* Single-threaded, asynchronous, non-blocking core with simple event-based API -* Support for LWIP and FreeRTOS-Plus-TCP stacks -* Tiny static and run-time footprint -* Source code is both ISO C and ISO C++ compliant -* Very easy to integrate: just copy - [mongoose.c](https://raw.githubusercontent.com/cesanta/mongoose/master/mongoose.c) and - [mongoose.h](https://raw.githubusercontent.com/cesanta/mongoose/master/mongoose.h) - files to your build tree - ## Concept Mongoose has three basic data structures: @@ -49,14 +29,14 @@ Mongoose's internals. An application that uses mongoose should follow a standard pattern of event-driven application: -1. Declare and initialize an event manager: +**Step 1.** Declare and initialize an event manager: ```c struct mg_mgr mgr; mg_mgr_init(&mgr); ``` -2. Create connections. For example, a server application should create listening +**Step 2.** Create connections. For example, a server application should create listening connections. When any connection is created (listening or outgoing), an event handler function must be specified. An event handler function defines connection's behavior. @@ -65,7 +45,7 @@ event-driven application: struct mg_connection *c = mg_http_listen(&mgr, "0.0.0.0:8000", fn, arg); ``` -3. Create an event loop by calling `mg_mgr_poll()`: +**Step 3.** Create an event loop by calling `mg_mgr_poll()`: ```c for (;;) { @@ -318,20 +298,17 @@ This example is a simple static HTTP server that serves current directory: ```c #include "mongoose.h" -static const char *s_web_root_dir = "."; -static const char *s_listening_address = "http://localhost:8000"; - -static void cb(struct mg_connection *c, int ev, void *ev_data, void *fn_data) { - struct mg_http_serve_opts opts = {.root_dir = s_web_root_dir}; +static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) { + struct mg_http_serve_opts opts = {.root_dir = "."}; // Serve local dir if (ev == MG_EV_HTTP_MSG) mg_http_serve_dir(c, ev_data, &opts); } int main(int argc, char *argv[]) { struct mg_mgr mgr; - mg_mgr_init(&mgr); - mg_http_listen(&mgr, s_listening_address, cb, &mgr); - for (;;) mg_mgr_poll(&mgr, 1000); - mg_mgr_free(&mgr); + mg_mgr_init(&mgr); // Init manager + mg_http_listen(&mgr, "http://localhost:8000", fn, &mgr); // Setup listener + for (;;) mg_mgr_poll(&mgr, 1000); // Event loop + mg_mgr_free(&mgr); // Cleanup return 0; } ``` @@ -343,8 +320,6 @@ This example is a simple TCP echo server that listens on port 1234: ```c #include "mongoose.h" -static const char *s_listening_address = "tcp://0.0.0.0:1234"; - static void cb(struct mg_connection *c, int ev, void *ev_data, void *fn_data) { if (ev == MG_EV_READ) { mg_send(c, c->recv.buf, c->recv.len); // Echo received data back @@ -355,7 +330,7 @@ static void cb(struct mg_connection *c, int ev, void *ev_data, void *fn_data) { int main(int argc, char *argv[]) { struct mg_mgr mgr; mg_mgr_init(&mgr); - mg_listen(&mgr, s_listening_address, cb, &mgr); + mg_listen(&mgr, "tcp://0.0.0.0:1234", cb, &mgr); for (;;) mg_mgr_poll(&mgr, 1000); mg_mgr_free(&mgr); return 0; @@ -927,7 +902,7 @@ void mg_http_bauth(struct mg_connection *, const char *user, const char *pass); Write a Basic `Authorization` header to the output buffer. -### mg\_http\_next_\multipart() +### mg\_http\_next\_multipart() ```c // Parameter for mg_http_next_multipart @@ -1131,16 +1106,18 @@ with a custom implementation. Just create your own `mg_random` function: struct mg_timer { int period_ms; // Timer period in milliseconds int flags; // Possible flags values below -#define MG_TIMER_REPEAT 1 // Call function periodically, otherwise run once -#define MG_TIMER_RUN_NOW 2 // Call immediately when timer is set void (*fn)(void *); // Function to call void *arg; // Function argument unsigned long expire; // Expiration timestamp in milliseconds struct mg_timer *next; // Linkage in g_timers list }; + +#define MG_TIMER_REPEAT 1 // Call function periodically, otherwise run once +#define MG_TIMER_RUN_NOW 2 // Call immediately when timer is set ``` -Timer structure. +Timer structure. Describes a software timer. Timer granularity is the same +as the `mg_mgr_poll()` timeout argument in the main event loop. ### mg\_timer\_init() diff --git a/examples/timers/main.c b/examples/timers/main.c index f00bf200d7c8fa4f094dec05916c0ec54885fc18..58c1fcc8d37f857bf2b9163ba71ca707c31f7d31 100644 --- a/examples/timers/main.c +++ b/examples/timers/main.c @@ -19,6 +19,7 @@ static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) { if (ev == MG_EV_HTTP_MSG) { struct mg_http_message *hm = (struct mg_http_message *) ev_data; mg_ws_upgrade(c, hm, NULL); + c->label[0] = 'W'; // Set some unique mark on a connection } else if (ev == MG_EV_WS_MSG) { // Got websocket frame. Received data is wm->data. Echo it back! struct mg_ws_message *wm = (struct mg_ws_message *) ev_data; @@ -30,14 +31,11 @@ static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) { static void timer_fn(void *arg) { struct mg_mgr *mgr = (struct mg_mgr *) arg; - struct mg_connection *c; // Broadcast "hi" message to all connected websocket clients. // Traverse over all connections - for (c = mgr->conns; c != NULL; c = c->next) { - // Send only to accepted websocket connections - if (c->is_accepted && c->is_websocket) { - mg_ws_send(c, "hi", 2, WEBSOCKET_OP_TEXT); - } + for (struct mg_connection *c = mgr->conns; c != NULL; c = c->next) { + // Send only to marked connections + if (c->label[0] == 'W') mg_ws_send(c, "hi", 2, WEBSOCKET_OP_TEXT); } } diff --git a/src/timer.h b/src/timer.h index db303ca072ddf7bf5418537505f2f795b594f4c3..dc25e15dc30e0b9836a863082cd728b7742e6dc6 100644 --- a/src/timer.h +++ b/src/timer.h @@ -3,14 +3,15 @@ struct mg_timer { unsigned long period_ms; // Timer period in milliseconds unsigned flags; // Possible flags values below -#define MG_TIMER_REPEAT 1 // Call function periodically, otherwise run once -#define MG_TIMER_RUN_NOW 2 // Call immediately when timer is set void (*fn)(void *); // Function to call void *arg; // Function argument unsigned long expire; // Expiration timestamp in milliseconds struct mg_timer *next; // Linkage in g_timers list }; +#define MG_TIMER_REPEAT 1 // Call function periodically, otherwise run once +#define MG_TIMER_RUN_NOW 2 // Call immediately when timer is set + extern struct mg_timer *g_timers; // Global list of timers void mg_timer_init(struct mg_timer *, unsigned long ms, unsigned,