mirror of
https://github.com/n0mjs710/ipsc2hbpc.git
synced 2026-11-08 04:18:24 +00:00
hbp: add login-handshake watchdog so a dead master triggers reconnect
The keepalive watchdog only guarded an established session; nothing covered the connection attempt itself. If the master never answered the RPTL (host down/unreachable, no ICMP to trigger error handling), the client sat in ST_LOGIN forever and never retried — so it stayed dead even after the master came back. Arm a login timer when the handshake starts, re-arm it at each step, and cancel it on become_connected/disconnect. On timeout it drives the existing disconnect -> reconnect path, re-sending RPTL until the master answers. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
1 parent
9c84d448f3
commit
c389e32c22
1 file changed
+29
-1
@@ -14,6 +14,7 @@
|
||||
#define KA_INTERVAL 5.0
|
||||
#define MAX_KA_AGE 15.0
|
||||
#define RECONNECT_DELAY 5.0
|
||||
#define LOGIN_TIMEOUT 15.0
|
||||
|
||||
enum { ST_LOGIN, ST_AUTH_SENT, ST_CONFIG_SENT, ST_OPTIONS_SENT, ST_CONNECTED, ST_DISCONNECTED };
|
||||
|
||||
@@ -28,11 +29,32 @@ struct hbp {
|
||||
uint8_t radio_id[4];
|
||||
ev_timer *ping_timer;
|
||||
ev_timer *reconnect_timer;
|
||||
ev_timer *login_timer;
|
||||
};
|
||||
|
||||
static void hbp_connect(hbp *hb);
|
||||
static void disconnect(hbp *hb, int send_rptcl);
|
||||
|
||||
/* Arm (or re-arm) the login-handshake watchdog. Covers every pre-CONNECTED
|
||||
* state: if the master goes away mid-handshake (or never answers the RPTL),
|
||||
* this fires and drives a disconnect -> reconnect instead of wedging in
|
||||
* ST_LOGIN forever. */
|
||||
static void login_timeout_cb(ev_loop *loop, void *ud)
|
||||
{
|
||||
(void)loop;
|
||||
hbp *hb = ud;
|
||||
hb->login_timer = NULL;
|
||||
LOGE(LOGN, "HBP: login handshake timed out (state %d, %.0fs) — reconnecting",
|
||||
hb->state, LOGIN_TIMEOUT);
|
||||
disconnect(hb, 0);
|
||||
}
|
||||
|
||||
static void arm_login_timer(hbp *hb)
|
||||
{
|
||||
if (hb->login_timer) ev_timer_cancel(hb->loop, hb->login_timer);
|
||||
hb->login_timer = ev_timer_after(hb->loop, LOGIN_TIMEOUT, login_timeout_cb, hb);
|
||||
}
|
||||
|
||||
/* ljust(n, '\0')[:n] */
|
||||
static void enc_field(uint8_t *dst, int n, const char *s)
|
||||
{
|
||||
@@ -88,12 +110,14 @@ static void on_rptack(hbp *hb, const uint8_t *d, int len)
|
||||
memcpy(pkt + 8, digest, 32);
|
||||
send_raw(hb, pkt, 40);
|
||||
hb->state = ST_AUTH_SENT;
|
||||
arm_login_timer(hb);
|
||||
LOGI(LOGN, "HBP: <- RPTACK+salt -> RPTK");
|
||||
} else if (hb->state == ST_AUTH_SENT) {
|
||||
uint8_t rptc[RPTC_LEN];
|
||||
int n = build_rptc(hb, rptc);
|
||||
send_raw(hb, rptc, n);
|
||||
hb->state = ST_CONFIG_SENT;
|
||||
arm_login_timer(hb);
|
||||
LOGI(LOGN, "HBP: <- RPTACK(auth) -> RPTC (%d bytes)", n);
|
||||
} else if (hb->state == ST_CONFIG_SENT) {
|
||||
if (hb->cfg->options[0]) {
|
||||
@@ -103,6 +127,7 @@ static void on_rptack(hbp *hb, const uint8_t *d, int len)
|
||||
enc_field(pkt + 8, 300, hb->cfg->options);
|
||||
send_raw(hb, pkt, 308);
|
||||
hb->state = ST_OPTIONS_SENT;
|
||||
arm_login_timer(hb);
|
||||
LOGI(LOGN, "HBP: <- RPTACK(config) -> RPTO options=%s", hb->cfg->options);
|
||||
} else {
|
||||
LOGI(LOGN, "HBP: <- RPTACK(config) CONNECTED to %s:%d",
|
||||
@@ -141,6 +166,7 @@ static void ping_cb(ev_loop *loop, void *ud)
|
||||
|
||||
static void become_connected(hbp *hb)
|
||||
{
|
||||
if (hb->login_timer) { ev_timer_cancel(hb->loop, hb->login_timer); hb->login_timer = NULL; }
|
||||
hb->state = ST_CONNECTED;
|
||||
hb->last_pong = ev_now(hb->loop);
|
||||
hb->ping_timer = ev_timer_after(hb->loop, KA_INTERVAL, ping_cb, hb);
|
||||
@@ -199,7 +225,8 @@ static void disconnect(hbp *hb, int send_rptcl)
|
||||
LOGI(LOGN, "HBP: -> RPTCL (clean disconnect)");
|
||||
}
|
||||
hb->state = ST_DISCONNECTED;
|
||||
if (hb->ping_timer) { ev_timer_cancel(hb->loop, hb->ping_timer); hb->ping_timer = NULL; }
|
||||
if (hb->ping_timer) { ev_timer_cancel(hb->loop, hb->ping_timer); hb->ping_timer = NULL; }
|
||||
if (hb->login_timer) { ev_timer_cancel(hb->loop, hb->login_timer); hb->login_timer = NULL; }
|
||||
if (hb->fd >= 0) { ev_del_fd(hb->loop, hb->fd); close(hb->fd); hb->fd = -1; }
|
||||
if (hb->active) schedule_reconnect(hb);
|
||||
}
|
||||
@@ -219,6 +246,7 @@ static void hbp_connect(hbp *hb)
|
||||
memcpy(pkt, "RPTL", 4);
|
||||
memcpy(pkt + 4, hb->radio_id, 4);
|
||||
send_raw(hb, pkt, 8);
|
||||
arm_login_timer(hb);
|
||||
LOGI(LOGN, "HBP: -> RPTL radio_id=%u", hb->cfg->hbp_repeater_id);
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user