From fd3881a9a32e2552551b9829bccf1a1cb90d8112 Mon Sep 17 00:00:00 2001 From: Pascal Martin Date: Sun, 26 Dec 2021 15:32:13 -0800 Subject: [PATCH] Add events to track clients and servers --- hc_http.c | 89 ++++++++++++++++++++++++++++++++++ hc_ntp.c | 2 + hc_ntp.h | 2 + public/events.html | 118 +++++++++++++++++++++++++++++++++++++++++++++ public/index.html | 1 + 5 files changed, 212 insertions(+) create mode 100644 public/events.html diff --git a/hc_http.c b/hc_http.c index 90b73be..490a957 100644 --- a/hc_http.c +++ b/hc_http.c @@ -46,9 +46,12 @@ #include "echttp_cors.h" #include "echttp_static.h" #include "houseportalclient.h" +#include "houselog.h" static pid_t parent; +static long hc_known_clients[256]; // Enough to store IP v4 address. +static long hc_known_servers[256]; // Enough to store IP v4 address. static hc_clock_status *clock_db = 0; static hc_nmea_status *nmea_db = 0; @@ -63,6 +66,7 @@ static char JsonBuffer[16384]; static void hc_background (int fd, int mode) { static time_t LastParentCheck = 0; static time_t LastRenewal = 0; + static time_t LastActivityCheck = 0; time_t now = time(0); @@ -90,6 +94,89 @@ static void hc_background (int fd, int mode) { LastRenewal = now; } } + + if (ntp_db && (now >= LastActivityCheck + 5)) { + + + // Generate events for new or unsynchronized clients. + // We generate a local "cache" of known clients to limit the number of + // events generated when the clent is not synchronized. The cache key + // is the low 7 bits of the IP address, plus the ninth bit: this works + // best for me because I have two subnets, while I don't have anywhere + // close to 127 machines at home. + // This should work fine for most home networks. + // + int i; + for (i = 0; i < HC_NTP_DEPTH; ++i) { + struct hc_ntp_client *client = ntp_db->clients + i; + + // Do not consider events that are empty or too old (risk of + // race condition) + // + if ((client->local.tv_sec < LastActivityCheck) + || (client->local.tv_sec == 0)) continue; + + // Do not consider events that were already detected. + // + if (client->logged) continue; + + if (abs(client->origin.tv_sec - client->local.tv_sec) > 600) { + houselog_event ("CLIENT", hc_broadcast_format (&(client->address)), + "ACTIVE", "NOT SYNCHRONIZED"); + } else { + long adr = ntohl(client->address.sin_addr.s_addr); + int hash = (int) ((adr & 0x7f) | ((adr & 0x100) >> 1)); + + int delta = + ((client->origin.tv_sec - client->local.tv_sec) * 1000) + + ((client->origin.tv_usec - client->local.tv_usec) / 1000); + + if ((hc_known_clients[hash] == adr) && (abs(delta) < 10000)) continue; + houselog_event ("CLIENT", hc_broadcast_format (&(client->address)), + "ACTIVE", "DELTA %d MS", delta); + + hc_known_clients[hash] = adr; + } + client->logged = 1; + } + + // Generate events for newly detected servers, using a similar cache + // as for clients to limit the rate of events when synchronized. + // + for (i = 0; i < HC_NTP_POOL; ++i) { + struct hc_ntp_server *server = ntp_db->pool + i; + + // Do not consider events that are empty or too old (risk of + // race condition) + // + if ((server->local.tv_sec < LastActivityCheck) + || (server->local.tv_sec == 0)) continue; + + // Do not consider events that were already detected. + // + if (server->logged) continue; + + if (abs(server->origin.tv_sec - server->local.tv_sec) > 600) { + houselog_event ("SERVER", server->name, "ACTIVE", + "STRATUM %d, NOT SYNCHRONIZED", server->stratum); + } else { + long adr = ntohl(server->address.sin_addr.s_addr); + int hash = (int) ((adr & 0x7f) | ((adr & 0x100) >> 1)); + + int delta = + ((server->origin.tv_sec - server->local.tv_sec) * 1000) + + ((server->origin.tv_usec - server->local.tv_usec) / 1000); + + if ((hc_known_servers[hash] == adr) && (abs(delta) < 10000)) continue; + houselog_event ("SERVER", server->name, "ACTIVE", + "STRATUM %d, DELTA %d MS", server->stratum, delta); + + hc_known_servers[hash] = adr; + } + server->logged = 1; + } + LastActivityCheck = now; + } } static void *hc_http_attach (const char *name) { @@ -474,6 +561,7 @@ void hc_http (int argc, const char **argv) { houseportal_initialize (argc, argv); use_houseportal = 1; } + houselog_initialize ("ntp", argc, argv); echttp_cors_allow_method("GET"); echttp_protect (0, hc_protect); @@ -485,6 +573,7 @@ void hc_http (int argc, const char **argv) { echttp_route_uri ("/ntp/server", hc_http_ntp); echttp_static_route ("/", "/usr/local/share/house/public"); echttp_background (&hc_background); + houselog_event ("SERVICE", "ntp", "STARTED", "ON %s", houselog_host()); echttp_loop(); exit (0); } diff --git a/hc_ntp.c b/hc_ntp.c index 3ac43df..eff3b74 100644 --- a/hc_ntp.c +++ b/hc_ntp.c @@ -305,6 +305,7 @@ static void hc_ntp_broadcastmsg (const ntpHeaderV3 *head, hc_ntp_status_db->pool[sender].stratum = head->stratum; hc_ntp_get_timestamp (&(hc_ntp_status_db->pool[sender].origin), &(head->transmit)); + hc_ntp_status_db->pool[sender].logged = 0; // Elect a time source. Choose the lowest stratum available. // @@ -413,6 +414,7 @@ static void hc_ntp_requestmsg (const ntpHeaderV3 *head, (&(hc_ntp_status_db->clients[hc_ntp_client_cursor].origin), &(ntpResponse.origin)); hc_ntp_status_db->clients[hc_ntp_client_cursor].local = *receive; + hc_ntp_status_db->clients[hc_ntp_client_cursor].logged = 0; } diff --git a/hc_ntp.h b/hc_ntp.h index d590de5..0d0f89f 100644 --- a/hc_ntp.h +++ b/hc_ntp.h @@ -44,6 +44,7 @@ struct hc_ntp_client { struct sockaddr_in address; struct timeval origin; struct timeval local; + int logged; }; struct hc_ntp_server { @@ -52,6 +53,7 @@ struct hc_ntp_server { short stratum; struct sockaddr_in address; char name[48]; + int logged; }; typedef struct { diff --git a/public/events.html b/public/events.html new file mode 100644 index 0000000..846f9c3 --- /dev/null +++ b/public/events.html @@ -0,0 +1,118 @@ + + + + + + + + + + + +
+ + + + + + +
PortalClockEvents
+
+

+ + + + + + + + +
TimeCategoryNameActionDescription
+ + + diff --git a/public/index.html b/public/index.html index bd9e37c..58c0c79 100644 --- a/public/index.html +++ b/public/index.html @@ -68,6 +68,7 @@ Portal Clock + Events