Add icon field to service, fix ping calculation, longer backoff for domain name resolution, make service deinit function

This commit is contained in:
Kouya Heika
2026-04-21 02:24:00 -05:00
parent fd5dbfc7d3
commit 75c3f063cf
2 changed files with 47 additions and 44 deletions

View File

@@ -8,7 +8,7 @@
#define POLLRDHUP 0x2000 #define POLLRDHUP 0x2000
#endif #endif
uint8_t report_queued = 0; uint8_t report_queued = 1;
uint64_t queued_time = 0; uint64_t queued_time = 0;
Vector services; Vector services;
Vector status_timeline; // of StatusPeroid* Vector status_timeline; // of StatusPeroid*
@@ -37,7 +37,7 @@ void* run_endpoint(void* endpoint) {
if (ret != 0) { if (ret != 0) {
fprintf(stderr, "getaddrinfo failed: %s\n", gai_strerror(ret)); fprintf(stderr, "getaddrinfo failed: %s\n", gai_strerror(ret));
queue_report((struct EndpointStatus){ self, DOWN, -1.0 }); queue_report((struct EndpointStatus){ self, DOWN, -1.0 });
sleep(self->backoff); sleep(self->backoff*2); // sleep longer to avoid spamming for DNS lookup
continue; continue;
} }
} }
@@ -50,9 +50,6 @@ void* run_endpoint(void* endpoint) {
int flags = fcntl(fd, F_GETFL, 0); int flags = fcntl(fd, F_GETFL, 0);
fcntl(fd, F_SETFL, flags | O_NONBLOCK); fcntl(fd, F_SETFL, flags | O_NONBLOCK);
struct timespec connect_start;
clock_gettime(CLOCK_REALTIME_ALARM, &connect_start);
int ret = connect(fd, rp->ai_addr, rp->ai_addrlen); int ret = connect(fd, rp->ai_addr, rp->ai_addrlen);
int error = 0; int error = 0;
if (strcmp(self->scheme, "tcp") == 0) { if (strcmp(self->scheme, "tcp") == 0) {
@@ -103,15 +100,7 @@ void* run_endpoint(void* endpoint) {
} }
} }
} }
if (fd > 0) { self->sockfd = fd;
struct timespec now;
clock_gettime(CLOCK_REALTIME_ALARM, &now);
double ping = (now.tv_sec - connect_start.tv_sec) * 1000.0 + (now.tv_nsec - connect_start.tv_nsec) / 1000000.0;
self->sockfd = fd;
self->last_errno = 0;
}
} }
if (self->sockfd < 0) { if (self->sockfd < 0) {
@@ -122,9 +111,8 @@ void* run_endpoint(void* endpoint) {
queue_report((struct EndpointStatus){ self, DOWN, -1.0 }); queue_report((struct EndpointStatus){ self, DOWN, -1.0 });
sleep(self->backoff); sleep(self->backoff);
continue; continue;
} } else self->last_errno = 0;
} }
struct pollfd pfd = { .fd = self->sockfd, .events = POLLIN | POLLERR | POLLHUP | POLLRDHUP }; struct pollfd pfd = { .fd = self->sockfd, .events = POLLIN | POLLERR | POLLHUP | POLLRDHUP };
int pollret = poll(&pfd, 1, (self->backoff > 0 ? self->backoff * 1000 : 10000)); int pollret = poll(&pfd, 1, (self->backoff > 0 ? self->backoff * 1000 : 10000));
@@ -138,19 +126,22 @@ void* run_endpoint(void* endpoint) {
if (recv(self->sockfd, NULL, sizeof(NULL), MSG_DONTWAIT | MSG_PEEK) < 0) { if (recv(self->sockfd, NULL, sizeof(NULL), MSG_DONTWAIT | MSG_PEEK) < 0) {
close(self->sockfd); close(self->sockfd);
self->sockfd = -1; self->sockfd = -1;
sleep(self->backoff);
continue; continue;
} }
} }
if ((pfd.revents & (POLLERR | POLLHUP | POLLRDHUP)) || pfd.events & POLLRDHUP) { if (pfd.revents & (POLLERR | POLLHUP | POLLRDHUP)) {
close(self->sockfd); close(self->sockfd);
self->sockfd = -1; self->sockfd = -1;
sleep(self->backoff);
continue; continue;
} }
if (strcmp(self->scheme, "udp") == 0 && send(self->sockfd, NULL, 0, 0) < 0) { if (strcmp(self->scheme, "udp") == 0 && send(self->sockfd, NULL, 0, 0) < 0) {
close(self->sockfd); close(self->sockfd);
self->sockfd = -1; self->sockfd = -1;
sleep(self->backoff);
continue; continue;
} }
@@ -158,8 +149,17 @@ void* run_endpoint(void* endpoint) {
time_t now = time(NULL); time_t now = time(NULL);
if (now - self->last_check >= self->backoff) { if (now - self->last_check >= self->backoff) {
self->last_check = now; self->last_check = now;
queue_report((struct EndpointStatus){ self, UP, self->last_ping });
double ping = 0.0;
if (strcmp(self->scheme, "udp") != 0) {
struct tcp_info info = {0}; socklen_t len = sizeof(info);
if (getsockopt(self->sockfd, IPPROTO_TCP, TCP_INFO, &info, &len) == 0) {
ping = info.tcpi_rtt / 1000.0;
}
}
queue_report((struct EndpointStatus){ self, UP, ping });
} }
sleep(self->backoff);
continue; continue;
} }
@@ -268,25 +268,11 @@ uint8_t add_endpoint(struct Service* self, const char* uri) {
return 0; return 0;
} }
enum State get_state(struct Service** self) {
Iterator it = vector_begin(&(*self)->endpoints);
Iterator end = vector_end(&(*self)->endpoints);
int up_count = 0; int total_count = (*self)->endpoints.size;
for (; !iterator_equals(&it, &end); iterator_increment(&it)) {
struct Endpoint* endpoint = *(struct Endpoint**)iterator_get(&it);
if (endpoint->last_state == UP)
up_count++;
}
if (up_count == total_count) return UP;
else if (up_count == 0) return DOWN;
else return PARTIAL;
}
void report() { void report() {
if (status_timeline.size + 1 >= status_timeline.capacity) if (status_timeline.size + 1 >= status_timeline.capacity)
vector_pop_front(&status_timeline); // remove (what should be) oldest entry vector_pop_front(&status_timeline); // remove (what should be) oldest entry
struct StatusPeroid* peroid = malloc(512); struct StatusPeroid* peroid = malloc(sizeof(struct StatusPeroid));
peroid->time = queued_time; peroid->time = queued_time;
vector_setup(&peroid->server_statuses, services.size, sizeof(struct ServerStatus*)); vector_setup(&peroid->server_statuses, services.size, sizeof(struct ServerStatus*));
@@ -305,7 +291,7 @@ struct ServerStatus* update_server_status(struct Service** self) {
struct Service* service = *self; struct Service* service = *self;
double pings[service->endpoints.size] = {}; double pings[service->endpoints.size] = {};
struct ServerStatus* server_status = malloc(512); struct ServerStatus* server_status = malloc(sizeof(struct ServerStatus));
server_status->service = service; server_status->service = service;
enum State service_state = DOWN; enum State service_state = DOWN;
@@ -322,28 +308,43 @@ struct ServerStatus* update_server_status(struct Service** self) {
pings[index] = estatus.ping = endpoint->last_ping; pings[index] = estatus.ping = endpoint->last_ping;
vector_push_back(&server_status->endpoint_statuses, &estatus); vector_push_back(&server_status->endpoint_statuses, &estatus);
if (index == 0) service_state = endpoint->last_state; if (index == 0) service_state = endpoint->last_state;
else if ((endpoint->last_state == DOWN && service_state == UP) || (endpoint->last_state == UP && service_state == DOWN)) else if (
service_state = PARTIAL; ((endpoint->last_state == DOWN || endpoint->last_state == NONE) && service_state == UP) ||
(endpoint->last_state == UP && (service_state == DOWN || service_state == NONE))
) service_state = PARTIAL;
index++; index++;
} }
if (service_state == NONE)
service_state = DOWN;
size_t pings_len = index; size_t pings_len = index;
double ping_sum = 0; double ping_sum = 0;
double avg_ping; double avg_ping = 0.0;
if (pings_len > 0) { for (int i = 0; i < pings_len; i++)
for (int i = 0; i < sizeof(pings)/sizeof(double); i++) if (pings[i] >= 0)
if (pings[i] >= 0) { ping_sum+=pings[i];
ping_sum+=pings[i]; if (ping_sum != 0 || pings_len != 0)
pings_len--;
}
avg_ping = ping_sum / pings_len; avg_ping = ping_sum / pings_len;
} else avg_ping = -1.0;
server_status->state = service_state; server_status->state = service_state;
server_status->ping = avg_ping; server_status->ping = avg_ping;
return server_status; return server_status;
} }
void deinit_service(struct Service** self) {
struct Service* service = *self;
Iterator it = vector_begin(&service->endpoints);
Iterator end = vector_end(&service->endpoints);
for (; !iterator_equals(&it, &end); iterator_increment(&it)) {
struct Endpoint* endpoint = *(struct Endpoint**)iterator_get(&it);
endpoint->enabled = 0;
int ret = pthread_join(endpoint->thread, NULL);
if (ret != 0)
fprintf(stderr, "Thread joining encountered an error: %d\n", ret);
}
}
const char* state_text(enum State state) { const char* state_text(enum State state) {
switch (state) { switch (state) {
case NONE: return "NONE"; case NONE: return "NONE";

View File

@@ -30,6 +30,7 @@ void load_service(struct Service** self);
uint8_t add_endpoint(struct Service* self, const char* uri); uint8_t add_endpoint(struct Service* self, const char* uri);
enum State get_state(struct Service** self); enum State get_state(struct Service** self);
struct ServerStatus* update_server_status(struct Service** self); struct ServerStatus* update_server_status(struct Service** self);
void deinit_service(struct Service** self);
const char* state_text(enum State state); const char* state_text(enum State state);
struct StatusPeroid { struct StatusPeroid {
@@ -71,6 +72,7 @@ struct Endpoint {
struct Service { struct Service {
char* id; char* id;
char* name; char* name;
char* icon;
char* text; char* text;
Vector endpoints; Vector endpoints;
enum State last_state; enum State last_state;