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

This commit is contained in:
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
#endif
uint8_t report_queued = 0;
uint8_t report_queued = 1;
uint64_t queued_time = 0;
Vector services;
Vector status_timeline; // of StatusPeroid*
@@ -37,7 +37,7 @@ void* run_endpoint(void* endpoint) {
if (ret != 0) {
fprintf(stderr, "getaddrinfo failed: %s\n", gai_strerror(ret));
queue_report((struct EndpointStatus){ self, DOWN, -1.0 });
sleep(self->backoff);
sleep(self->backoff*2); // sleep longer to avoid spamming for DNS lookup
continue;
}
}
@@ -50,9 +50,6 @@ void* run_endpoint(void* endpoint) {
int flags = fcntl(fd, F_GETFL, 0);
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 error = 0;
if (strcmp(self->scheme, "tcp") == 0) {
@@ -103,15 +100,7 @@ void* run_endpoint(void* endpoint) {
}
}
}
if (fd > 0) {
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;
}
self->sockfd = fd;
}
if (self->sockfd < 0) {
@@ -122,9 +111,8 @@ void* run_endpoint(void* endpoint) {
queue_report((struct EndpointStatus){ self, DOWN, -1.0 });
sleep(self->backoff);
continue;
}
} else self->last_errno = 0;
}
struct pollfd pfd = { .fd = self->sockfd, .events = POLLIN | POLLERR | POLLHUP | POLLRDHUP };
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) {
close(self->sockfd);
self->sockfd = -1;
sleep(self->backoff);
continue;
}
}
if ((pfd.revents & (POLLERR | POLLHUP | POLLRDHUP)) || pfd.events & POLLRDHUP) {
if (pfd.revents & (POLLERR | POLLHUP | POLLRDHUP)) {
close(self->sockfd);
self->sockfd = -1;
sleep(self->backoff);
continue;
}
if (strcmp(self->scheme, "udp") == 0 && send(self->sockfd, NULL, 0, 0) < 0) {
close(self->sockfd);
self->sockfd = -1;
sleep(self->backoff);
continue;
}
@@ -158,8 +149,17 @@ void* run_endpoint(void* endpoint) {
time_t now = time(NULL);
if (now - self->last_check >= self->backoff) {
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;
}
@@ -268,25 +268,11 @@ uint8_t add_endpoint(struct Service* self, const char* uri) {
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() {
if (status_timeline.size + 1 >= status_timeline.capacity)
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;
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;
double pings[service->endpoints.size] = {};
struct ServerStatus* server_status = malloc(512);
struct ServerStatus* server_status = malloc(sizeof(struct ServerStatus));
server_status->service = service;
enum State service_state = DOWN;
@@ -322,28 +308,43 @@ struct ServerStatus* update_server_status(struct Service** self) {
pings[index] = estatus.ping = endpoint->last_ping;
vector_push_back(&server_status->endpoint_statuses, &estatus);
if (index == 0) service_state = endpoint->last_state;
else if ((endpoint->last_state == DOWN && service_state == UP) || (endpoint->last_state == UP && service_state == DOWN))
service_state = PARTIAL;
else if (
((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++;
}
if (service_state == NONE)
service_state = DOWN;
size_t pings_len = index;
double ping_sum = 0;
double avg_ping;
if (pings_len > 0) {
for (int i = 0; i < sizeof(pings)/sizeof(double); i++)
if (pings[i] >= 0) {
ping_sum+=pings[i];
pings_len--;
}
double avg_ping = 0.0;
for (int i = 0; i < pings_len; i++)
if (pings[i] >= 0)
ping_sum+=pings[i];
if (ping_sum != 0 || pings_len != 0)
avg_ping = ping_sum / pings_len;
} else avg_ping = -1.0;
server_status->state = service_state;
server_status->ping = avg_ping;
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) {
switch (state) {
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);
enum State get_state(struct Service** self);
struct ServerStatus* update_server_status(struct Service** self);
void deinit_service(struct Service** self);
const char* state_text(enum State state);
struct StatusPeroid {
@@ -71,6 +72,7 @@ struct Endpoint {
struct Service {
char* id;
char* name;
char* icon;
char* text;
Vector endpoints;
enum State last_state;