feat(client): re-resolve the server hostnames at the DNS TTL
hbc, hbc_mini.py and hbc_mini.c resolved the server once at startup, so an address change needed a client restart. They now re-resolve every TTL seconds (smallest A/AAAA TTL, floor 30s, 300s when unknown) and re-point, add or drop connections to follow the new addresses; a failed lookup keeps the current ones. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -226,6 +226,55 @@ static int live_mode(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ---- server address re-resolution (dns_apply) ---- */
|
||||
|
||||
static void dns_conn(int i, int af, const char *addr) {
|
||||
memset(&g_conns[i], 0, sizeof(conn_t));
|
||||
g_conns[i].conn_id = i + 1; g_conns[i].af = af; g_conns[i].port = 5;
|
||||
snprintf(g_conns[i].addr, sizeof(g_conns[i].addr), "%s", addr);
|
||||
conn_open(&g_conns[i]);
|
||||
}
|
||||
|
||||
static void dns_push(int n, const dns_addr_t *a) {
|
||||
memcpy(g_dns.addrs, a, n * sizeof(*a)); g_dns.n = n; g_dns.ready = true;
|
||||
}
|
||||
|
||||
static void test_dns_apply_follows_changes(void) {
|
||||
int id = 3;
|
||||
dns_conn(0, AF_INET, "1.1.1.1"); dns_conn(1, AF_INET6, "2001:db8::1"); g_nconns = 2;
|
||||
|
||||
dns_addr_t moved[2] = {{AF_INET, "9.9.9.9"}, {AF_INET6, "2001:db8::9"}};
|
||||
dns_push(2, moved); dns_apply(&id, "me", 5);
|
||||
CHECK(g_nconns == 2);
|
||||
CHECK_STR(g_conns[0].addr, "9.9.9.9");
|
||||
CHECK_STR(g_conns[1].addr, "2001:db8::9");
|
||||
|
||||
/* the first connection's address vanishes and nothing replaces it: it survives, the other goes */
|
||||
dns_addr_t v6only[1] = {{AF_INET6, "2001:db8::9"}};
|
||||
dns_push(1, v6only); dns_apply(&id, "me", 5);
|
||||
CHECK(g_nconns == 1);
|
||||
CHECK_STR(g_conns[0].addr, "2001:db8::9");
|
||||
CHECK(g_conns[0].af == AF_INET6);
|
||||
|
||||
dns_addr_t grown[2] = {{AF_INET6, "2001:db8::9"}, {AF_INET, "5.5.5.5"}};
|
||||
dns_push(2, grown); dns_apply(&id, "me", 5);
|
||||
CHECK(g_nconns == 2);
|
||||
CHECK_STR(g_conns[1].addr, "5.5.5.5");
|
||||
CHECK(g_conns[1].conn_id == 3);
|
||||
|
||||
dns_push(2, grown); dns_apply(&id, "me", 5); /* unchanged: nothing happens */
|
||||
CHECK(g_nconns == 2 && id == 4);
|
||||
for (int i = 0; i < g_nconns; i++) conn_close(&g_conns[i]);
|
||||
g_nconns = 0;
|
||||
}
|
||||
|
||||
static void test_dns_ttl_unknown_for_ip_literals(void) {
|
||||
CHECK(dns_host_ttl("192.0.2.1", 0) == -1);
|
||||
CHECK(dns_host_ttl("2001:db8::1", 0) == -1);
|
||||
const char *h[] = {"192.0.2.1"}; dns_ctx_t x = {h, 1, 5, 0};
|
||||
CHECK(dns_refresh_delay(&x) == DNS_DEFAULT_TTL);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc > 1 && !strcmp(argv[1], "--live")) return live_mode();
|
||||
test_gateway_parsers();
|
||||
@@ -238,6 +287,8 @@ int main(int argc, char **argv) {
|
||||
test_route_loss_then_return_pings_immediately();
|
||||
test_missing_ping_stays_unknown_even_after_route_loss();
|
||||
test_unsupported_family_is_unknown();
|
||||
test_dns_apply_follows_changes();
|
||||
test_dns_ttl_unknown_for_ip_literals();
|
||||
printf("%d checks, %d failed\n", g_run, g_fail);
|
||||
return g_fail ? 1 : 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user