From 6db0485c7b233f07adbbc22a113736015c124e61 Mon Sep 17 00:00:00 2001 From: Sergey Lyubka Date: Fri, 6 May 2022 20:19:40 +0100 Subject: [PATCH] Set c->loc for accepted and UDP connections --- examples/http-restful-server/main.c | 19 ++++++++++++++++--- examples/zephyr/http-server/src/main.c | 17 +++++++++++++++-- mongoose.c | 26 +++++++++++++++----------- src/dns.c | 2 +- src/sntp.c | 6 +++--- src/sock.c | 18 +++++++++++------- 6 files changed, 61 insertions(+), 27 deletions(-) diff --git a/examples/http-restful-server/main.c b/examples/http-restful-server/main.c index 1a51a107..95c24916 100644 --- a/examples/http-restful-server/main.c +++ b/examples/http-restful-server/main.c @@ -4,7 +4,7 @@ // HTTP server example. This server serves both static and dynamic content. // It opens two ports: plain HTTP on port 8000 and HTTP on port 8443. // It implements the following endpoints: -// /api/f1 - respond with JSON string {"result": 123} +// /api/stats - respond with free-formatted stats on current connections // /api/f2/:id - wildcard example, respond with JSON string {"result": "URI"} // any other URI serves static files from s_root_dir // @@ -30,8 +30,21 @@ static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) { mg_tls_init(c, &opts); } else if (ev == MG_EV_HTTP_MSG) { struct mg_http_message *hm = (struct mg_http_message *) ev_data; - if (mg_http_match_uri(hm, "/api/f1")) { - mg_http_reply(c, 200, "", "{\"result\": %d}\n", 123); // Serve REST + if (mg_http_match_uri(hm, "/api/stats")) { + // Print some statistics about currently established connections + mg_printf(c, "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"); + mg_http_printf_chunk(c, "ID PROTO TYPE LOCAL REMOTE\n"); + for (struct mg_connection *t = c->mgr->conns; t != NULL; t = t->next) { + char loc[40], rem[40]; + mg_http_printf_chunk(c, "%-3lu %4s %s %-15s %s\n", t->id, + t->is_udp ? "UDP" : "TCP", + t->is_listening ? "LISTENING" + : t->is_accepted ? "ACCEPTED " + : "CONNECTED", + mg_straddr(&t->loc, loc, sizeof(loc)), + mg_straddr(&t->rem, rem, sizeof(rem))); + } + mg_http_printf_chunk(c, ""); // Don't forget the last empty chunk } else if (mg_http_match_uri(hm, "/api/f2/*")) { mg_http_reply(c, 200, "", "{\"result\": \"%.*s\"}\n", (int) hm->uri.len, hm->uri.ptr); diff --git a/examples/zephyr/http-server/src/main.c b/examples/zephyr/http-server/src/main.c index d5239a47..406b1cbe 100644 --- a/examples/zephyr/http-server/src/main.c +++ b/examples/zephyr/http-server/src/main.c @@ -1,8 +1,8 @@ // Copyright (c) 2020 Cesanta Software Limited // All rights reserved -#include "mongoose.h" #include "certs.h" +#include "mongoose.h" static const char *s_debug_level = "3"; static const char *s_web_dir = "/"; @@ -21,7 +21,20 @@ static void wcb(struct mg_connection *c, int ev, void *ev_data, void *fn_data) { MG_INFO(("%.*s %.*s %ld", (int) hm->method.len, hm->method.ptr, (int) hm->uri.len, hm->uri.ptr, (long) hm->body.len)); if (mg_http_match_uri(hm, "/api/#")) { // REST API requests - mg_http_reply(c, 200, NULL, "hi\n"); // Construct dynamic response + // Print some statistics about currently established connections + mg_printf(c, "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"); + mg_http_printf_chunk(c, "ID PROTO TYPE LOCAL REMOTE\n"); + for (struct mg_connection *t = c->mgr->conns; t != NULL; t = t->next) { + char loc[40], rem[40]; + mg_http_printf_chunk(c, "%-3lu %4s %s %-15s %s\n", t->id, + t->is_udp ? "UDP" : "TCP", + t->is_listening ? "LISTENING" + : t->is_accepted ? "ACCEPTED " + : "CONNECTED", + mg_straddr(&t->loc, loc, sizeof(loc)), + mg_straddr(&t->rem, rem, sizeof(rem))); + } + mg_http_printf_chunk(c, ""); // Don't forget the last empty chunk } else { struct mg_http_serve_opts opts = {.root_dir = s_web_dir}; // Serve mg_http_serve_dir(c, hm, &opts); // static files diff --git a/mongoose.c b/mongoose.c index d27fb4cf..f5eee27e 100644 --- a/mongoose.c +++ b/mongoose.c @@ -275,7 +275,7 @@ static void dns_cb(struct mg_connection *c, int ev, void *ev_data, char buf[100]; dm.addr.port = d->c->rem.port; // Save port d->c->rem = dm.addr; // Copy resolved address - MG_DEBUG(("%lu %s resolved to %s", d->c->id, dm.name, + MG_DEBUG(("%lu %s is %s", d->c->id, dm.name, mg_ntoa(&d->c->rem, buf, sizeof(buf)))); mg_connect_resolved(d->c); #if MG_ENABLE_IPV6 @@ -3069,8 +3069,8 @@ static void sntp_cb(struct mg_connection *c, int ev, void *evd, void *fnd) { int64_t milliseconds = mg_sntp_parse(c->recv.buf, c->recv.len); if (milliseconds > 0) { mg_call(c, MG_EV_SNTP_TIME, (uint64_t *) &milliseconds); - MG_DEBUG(("%u.%u", (unsigned) (milliseconds / 1000), - (unsigned) (milliseconds % 1000))); + MG_VERBOSE(("%u.%u", (unsigned) (milliseconds / 1000), + (unsigned) (milliseconds % 1000))); } c->recv.len = 0; // Clear receive buffer } else if (ev == MG_EV_CONNECT) { @@ -3088,7 +3088,7 @@ void mg_sntp_send(struct mg_connection *c, unsigned long utc) { uint8_t buf[48] = {0}; buf[0] = (0 << 6) | (4 << 3) | 3; mg_send(c, buf, sizeof(buf)); - MG_DEBUG(("%lu ct %lu", c->id, utc)); + (void) utc; } } @@ -3204,6 +3204,14 @@ bool mg_sock_conn_reset(void) { #endif } +static void setlocaddr(SOCKET fd, struct mg_addr *addr) { + union usa usa; + socklen_t n = sizeof(usa); + if (getsockname(fd, &usa.sa, &n) == 0) { + tomgaddr(&usa, addr, n != sizeof(usa.sin)); + } +} + static void iolog(struct mg_connection *c, char *buf, long n, bool r) { if (n == 0) { // Do nothing @@ -3244,6 +3252,7 @@ static long mg_sock_send(struct mg_connection *c, const void *buf, size_t len) { union usa usa; socklen_t slen = tousa(&c->rem, &usa); n = sendto(FD(c), (char *) buf, len, 0, &usa.sa, slen); + if (n > 0) setlocaddr(FD(c), &c->loc); } else { n = send(FD(c), (char *) buf, len, MSG_NONBLOCKING); } @@ -3321,12 +3330,7 @@ bool mg_open_listener(struct mg_connection *c, const char *url) { // NOTE(lsm): FreeRTOS uses backlog value as a connection limit (type == SOCK_DGRAM || listen(fd, MG_SOCK_LISTEN_BACKLOG_SIZE) == 0)) { // In case port was set to 0, get the real port number - if (getsockname(fd, &usa.sa, &slen) == 0) { - c->loc.port = usa.sin.sin_port; -#if MG_ENABLE_IPV6 - if (c->loc.is_ip6) c->loc.port = usa.sin6.sin6_port; -#endif - } + setlocaddr(fd, &c->loc); mg_set_non_blocking_mode(fd); } else if (fd != INVALID_SOCKET) { s_err = MG_SOCK_ERRNO; @@ -3500,8 +3504,8 @@ static void accept_conn(struct mg_mgr *mgr, struct mg_connection *lsn) { setsockopts(c); c->is_accepted = 1; c->is_hexdumping = lsn->is_hexdumping; - c->pfn = lsn->pfn; c->loc = lsn->loc; + c->pfn = lsn->pfn; c->pfn_data = lsn->pfn_data; c->fn = lsn->fn; c->fn_data = lsn->fn_data; diff --git a/src/dns.c b/src/dns.c index b560c444..a3ea8c67 100644 --- a/src/dns.c +++ b/src/dns.c @@ -163,7 +163,7 @@ static void dns_cb(struct mg_connection *c, int ev, void *ev_data, char buf[100]; dm.addr.port = d->c->rem.port; // Save port d->c->rem = dm.addr; // Copy resolved address - MG_DEBUG(("%lu %s resolved to %s", d->c->id, dm.name, + MG_DEBUG(("%lu %s is %s", d->c->id, dm.name, mg_ntoa(&d->c->rem, buf, sizeof(buf)))); mg_connect_resolved(d->c); #if MG_ENABLE_IPV6 diff --git a/src/sntp.c b/src/sntp.c index a528234e..ebece8b3 100644 --- a/src/sntp.c +++ b/src/sntp.c @@ -33,8 +33,8 @@ static void sntp_cb(struct mg_connection *c, int ev, void *evd, void *fnd) { int64_t milliseconds = mg_sntp_parse(c->recv.buf, c->recv.len); if (milliseconds > 0) { mg_call(c, MG_EV_SNTP_TIME, (uint64_t *) &milliseconds); - MG_DEBUG(("%u.%u", (unsigned) (milliseconds / 1000), - (unsigned) (milliseconds % 1000))); + MG_VERBOSE(("%u.%u", (unsigned) (milliseconds / 1000), + (unsigned) (milliseconds % 1000))); } c->recv.len = 0; // Clear receive buffer } else if (ev == MG_EV_CONNECT) { @@ -52,7 +52,7 @@ void mg_sntp_send(struct mg_connection *c, unsigned long utc) { uint8_t buf[48] = {0}; buf[0] = (0 << 6) | (4 << 3) | 3; mg_send(c, buf, sizeof(buf)); - MG_DEBUG(("%lu ct %lu", c->id, utc)); + (void) utc; } } diff --git a/src/sock.c b/src/sock.c index a4bec3e2..e00e27e4 100644 --- a/src/sock.c +++ b/src/sock.c @@ -99,6 +99,14 @@ bool mg_sock_conn_reset(void) { #endif } +static void setlocaddr(SOCKET fd, struct mg_addr *addr) { + union usa usa; + socklen_t n = sizeof(usa); + if (getsockname(fd, &usa.sa, &n) == 0) { + tomgaddr(&usa, addr, n != sizeof(usa.sin)); + } +} + static void iolog(struct mg_connection *c, char *buf, long n, bool r) { if (n == 0) { // Do nothing @@ -139,6 +147,7 @@ static long mg_sock_send(struct mg_connection *c, const void *buf, size_t len) { union usa usa; socklen_t slen = tousa(&c->rem, &usa); n = sendto(FD(c), (char *) buf, len, 0, &usa.sa, slen); + if (n > 0) setlocaddr(FD(c), &c->loc); } else { n = send(FD(c), (char *) buf, len, MSG_NONBLOCKING); } @@ -216,12 +225,7 @@ bool mg_open_listener(struct mg_connection *c, const char *url) { // NOTE(lsm): FreeRTOS uses backlog value as a connection limit (type == SOCK_DGRAM || listen(fd, MG_SOCK_LISTEN_BACKLOG_SIZE) == 0)) { // In case port was set to 0, get the real port number - if (getsockname(fd, &usa.sa, &slen) == 0) { - c->loc.port = usa.sin.sin_port; -#if MG_ENABLE_IPV6 - if (c->loc.is_ip6) c->loc.port = usa.sin6.sin6_port; -#endif - } + setlocaddr(fd, &c->loc); mg_set_non_blocking_mode(fd); } else if (fd != INVALID_SOCKET) { s_err = MG_SOCK_ERRNO; @@ -395,8 +399,8 @@ static void accept_conn(struct mg_mgr *mgr, struct mg_connection *lsn) { setsockopts(c); c->is_accepted = 1; c->is_hexdumping = lsn->is_hexdumping; - c->pfn = lsn->pfn; c->loc = lsn->loc; + c->pfn = lsn->pfn; c->pfn_data = lsn->pfn_data; c->fn = lsn->fn; c->fn_data = lsn->fn_data;