diff --git a/docs/README.md b/docs/README.md index a39f8ee4..43e80f24 100644 --- a/docs/README.md +++ b/docs/README.md @@ -760,6 +760,23 @@ Return value: `true` if data has been sent, `false` otherwise Usage example: see [examples/multi-threaded](https://github.com/cesanta/mongoose/tree/master/examples/multi-threaded). +### mg\_hello() + +```c +void mg_hello(const char *url); +``` + +A convenience function that starts a simple web server on a given listening +URL. This function does not return until a "/quit" request is received. A +server handles the following URIs: + +- `/quit` - quit the server, and exit the function +- `/debug` - set debug level, expect `{"level": 3}` as a POST payload +- For all other URIs, `hi` is returned as a response + +Parameters: +- `url` - a listening URL, for example `http://0.0.0.0:8000` + ## HTTP diff --git a/mongoose.c b/mongoose.c index 845355bc..49a70a21 100644 --- a/mongoose.c +++ b/mongoose.c @@ -3488,6 +3488,34 @@ struct mg_timer *mg_timer_add(struct mg_mgr *mgr, uint64_t milliseconds, return t; } +static void mg_hfn(struct mg_connection *c, int ev, void *ev_data, void *fnd) { + if (ev == MG_EV_HTTP_MSG) { + struct mg_http_message *hm = (struct mg_http_message *) ev_data; + if (mg_http_match_uri(hm, "/quit")) { + mg_http_reply(c, 200, "", "ok\n"); + c->is_draining = 1; + c->label[0] = 'X'; + } else if (mg_http_match_uri(hm, "/debug")) { + int level = (int) mg_json_get_long(hm->body, "$.level", MG_LL_DEBUG); + mg_log_set(level); + mg_http_reply(c, 200, "", "Debug level set to %d\n", level); + } else { + mg_http_reply(c, 200, "", "hi\n"); + } + } else if (ev == MG_EV_CLOSE) { + if (c->label[0] == 'X') *(bool *) fnd = true; + } +} + +void mg_hello(const char *url) { + struct mg_mgr mgr; + bool done = false; + mg_mgr_init(&mgr); + if (mg_http_listen(&mgr, url, mg_hfn, &done) == NULL) done = true; + while (done == false) mg_mgr_poll(&mgr, 100); + mg_mgr_free(&mgr); +} + void mg_mgr_free(struct mg_mgr *mgr) { struct mg_connection *c; struct mg_timer *tmp, *t = mgr->timers; diff --git a/mongoose.h b/mongoose.h index 699beddb..45431248 100644 --- a/mongoose.h +++ b/mongoose.h @@ -1103,6 +1103,7 @@ char *mg_straddr(struct mg_addr *, char *, size_t); bool mg_aton(struct mg_str str, struct mg_addr *addr); char *mg_ntoa(const struct mg_addr *addr, char *buf, size_t len); int mg_mkpipe(struct mg_mgr *, mg_event_handler_t, void *, bool udp); +void mg_hello(const char *url); // These functions are used to integrate with custom network stacks struct mg_connection *mg_alloc_conn(struct mg_mgr *); diff --git a/src/net.c b/src/net.c index c0a9e5fe..b8dcb286 100644 --- a/src/net.c +++ b/src/net.c @@ -1,7 +1,7 @@ -#include "net.h" #include "dns.h" #include "fmt.h" #include "log.h" +#include "net.h" #include "timer.h" #include "tls.h" @@ -230,6 +230,34 @@ struct mg_timer *mg_timer_add(struct mg_mgr *mgr, uint64_t milliseconds, return t; } +static void mg_hfn(struct mg_connection *c, int ev, void *ev_data, void *fnd) { + if (ev == MG_EV_HTTP_MSG) { + struct mg_http_message *hm = (struct mg_http_message *) ev_data; + if (mg_http_match_uri(hm, "/quit")) { + mg_http_reply(c, 200, "", "ok\n"); + c->is_draining = 1; + c->label[0] = 'X'; + } else if (mg_http_match_uri(hm, "/debug")) { + int level = (int) mg_json_get_long(hm->body, "$.level", MG_LL_DEBUG); + mg_log_set(level); + mg_http_reply(c, 200, "", "Debug level set to %d\n", level); + } else { + mg_http_reply(c, 200, "", "hi\n"); + } + } else if (ev == MG_EV_CLOSE) { + if (c->label[0] == 'X') *(bool *) fnd = true; + } +} + +void mg_hello(const char *url) { + struct mg_mgr mgr; + bool done = false; + mg_mgr_init(&mgr); + if (mg_http_listen(&mgr, url, mg_hfn, &done) == NULL) done = true; + while (done == false) mg_mgr_poll(&mgr, 100); + mg_mgr_free(&mgr); +} + void mg_mgr_free(struct mg_mgr *mgr) { struct mg_connection *c; struct mg_timer *tmp, *t = mgr->timers; diff --git a/src/net.h b/src/net.h index b01b0fbf..d58a6f5e 100644 --- a/src/net.h +++ b/src/net.h @@ -90,6 +90,7 @@ char *mg_straddr(struct mg_addr *, char *, size_t); bool mg_aton(struct mg_str str, struct mg_addr *addr); char *mg_ntoa(const struct mg_addr *addr, char *buf, size_t len); int mg_mkpipe(struct mg_mgr *, mg_event_handler_t, void *, bool udp); +void mg_hello(const char *url); // These functions are used to integrate with custom network stacks struct mg_connection *mg_alloc_conn(struct mg_mgr *);