diff --git a/README.md b/README.md index ef69982..94b1bf6 100644 --- a/README.md +++ b/README.md @@ -119,6 +119,7 @@ Select rtty in menuconfig and compile it -p, --port=number Server port(Default is 5912) -d, --description=string Add a description to the device(Maximum 126 bytes) -a Auto reconnect to the server + -i number Set heartbeat interval in seconds(Default is 5s) -s SSL on -C, --cacert CA certificate to verify peer against -x, --insecure Allow insecure server connections when using SSL diff --git a/README_ZH.md b/README_ZH.md index 1c56739..403fd40 100644 --- a/README_ZH.md +++ b/README_ZH.md @@ -117,6 +117,7 @@ rtty非常适合远程维护您的或者您的公司的部署在全球各地的 -p, --port=number Server port(Default is 5912) -d, --description=string Add a description to the device(Maximum 126 bytes) -a Auto reconnect to the server + -i number Set heartbeat interval in seconds(Default is 5s) -s SSL on -C, --cacert CA certificate to verify peer against -x, --insecure Allow insecure server connections when using SSL diff --git a/src/main.c b/src/main.c index 04f2bb8..34a9698 100644 --- a/src/main.c +++ b/src/main.c @@ -85,6 +85,7 @@ static void usage(const char *prog) " -p, --port=number Server port(Default is 5912)\n" " -d, --description=string Add a description to the device(Maximum 126 bytes)\n" " -a Auto reconnect to the server\n" + " -i number Set heartbeat interval in seconds(Default is 5s)\n" #ifdef SSL_SUPPORT " -s SSL on\n" " -C, --cacert CA certificate to verify peer against\n" @@ -106,12 +107,13 @@ static void usage(const char *prog) int main(int argc, char **argv) { - char shortopts[32] = "I:h:p:d:aDt:f:RS:vV"; + char shortopts[32] = "I:i:h:p:d:aDt:f:RS:vV"; struct ev_loop *loop = EV_DEFAULT; struct ev_signal signal_watcher; bool background = false; bool verbose = false; struct rtty rtty = { + .heartbeat = 5.0, .host = "localhost", .port = 5912, .loop = loop, @@ -140,6 +142,13 @@ int main(int argc, char **argv) case 'I': rtty.devid = optarg; break; + case 'i': + rtty.heartbeat = atof(optarg); + if (rtty.heartbeat < 5) { + rtty.heartbeat = 5.0; + log_warn("Heartbeat interval too short, set to 5s\n"); + } + break; case 'h': rtty.host = optarg; break; diff --git a/src/rtty.c b/src/rtty.c index 1f2be9c..631995f 100644 --- a/src/rtty.c +++ b/src/rtty.c @@ -295,10 +295,11 @@ void rtty_exit(struct rtty *rtty) struct tty *tty, *ntty; if (rtty->sock < 0) - return; + goto done; ev_io_stop(rtty->loop, &rtty->ior); ev_io_stop(rtty->loop, &rtty->iow); + ev_timer_stop(rtty->loop, &rtty->tmr); buffer_free(&rtty->rb); buffer_free(&rtty->wb); @@ -316,18 +317,24 @@ void rtty_exit(struct rtty *rtty) close(rtty->sock); rtty->sock = -1; + rtty->registered = false; http_conns_free(&rtty->http_conns); rtty_run_state(RTTY_STATE_DISCONNECTED); - if (!rtty->reconnect) +done: + if (!rtty->reconnect) { ev_break(rtty->loop, EVBREAK_ALL); + } else { + ev_timer_set(&rtty->tmr, 5.0, 0); + ev_timer_start(rtty->loop, &rtty->tmr); + } } static void rtty_register(struct rtty *rtty) { - size_t len = 4 + strlen(rtty->devid); + size_t len = 6 + strlen(rtty->devid); struct buffer *wb = &rtty->wb; if (rtty->description) @@ -340,6 +347,7 @@ static void rtty_register(struct rtty *rtty) buffer_put_u16be(wb, len); buffer_put_u8(wb, RTTY_PROTO_VER); + buffer_put_u16be(wb, rtty->heartbeat); buffer_put_string(wb, rtty->devid); buffer_put_u8(wb, '\0'); @@ -354,6 +362,9 @@ static void rtty_register(struct rtty *rtty) ev_io_start(rtty->loop, &rtty->iow); + ev_timer_set(&rtty->tmr, 5.0, 0); + ev_timer_start(rtty->loop, &rtty->tmr); + log_debug("send msg: register\n"); } @@ -464,6 +475,9 @@ static int parse_msg(struct rtty *rtty) buffer_pull(rb, NULL, msglen - 1); log_info("register success\n"); rtty_run_state(RTTY_STATE_CONNECTED); + rtty->registered = true; + ev_timer_set(&rtty->tmr, 0, rtty->heartbeat); + ev_timer_again(rtty->loop, &rtty->tmr); break; case MSG_TYPE_LOGIN: @@ -481,6 +495,9 @@ static int parse_msg(struct rtty *rtty) break; case MSG_TYPE_HEARTBEAT: + rtty->wait_heartbeat = false; + ev_timer_set(&rtty->tmr, 0, rtty->heartbeat); + ev_timer_again(rtty->loop, &rtty->tmr); break; case MSG_TYPE_HTTP: @@ -580,9 +597,6 @@ static void on_net_read(struct ev_loop *loop, struct ev_io *w, int revents) } } - rtty->ninactive = 0; - rtty->active = ev_now(loop); - if (parse_msg(rtty)) goto err; @@ -648,15 +662,13 @@ static void on_net_connected(int sock, void *arg) struct rtty *rtty = arg; if (sock < 0) { - if (!rtty->reconnect) - ev_break(rtty->loop, EVBREAK_ALL); + rtty_exit(rtty); return; } log_info("connected to server\n"); rtty->sock = sock; - rtty->ninactive = 0; ev_io_init(&rtty->ior, on_net_read, sock, EV_READ); ev_io_start(rtty->loop, &rtty->ior); @@ -681,42 +693,40 @@ static void on_net_connected(int sock, void *arg) static void rtty_timer_cb(struct ev_loop *loop, struct ev_timer *w, int revents) { struct rtty *rtty = container_of(w, struct rtty, tmr); - ev_tstamp now = ev_now(loop); + struct sysinfo info = {}; if (rtty->sock < 0) { - if (now - rtty->active < 5) - return; - rtty->active = now; log_err("rtty reconnecting...\n"); tcp_connect(rtty->loop, rtty->host, rtty->port, on_net_connected, rtty); return; } - if (now - rtty->active > RTTY_HEARTBEAT_INTEVAL * 3 / 2) { - log_err("Inactive too long time\n"); - if (rtty->ninactive++ > 1) { - log_err("Inactive 3 times, now exit\n"); - rtty_exit(rtty); - return; - } - rtty->active = now; + if (!rtty->registered) { + log_err("rtty register timeout\n"); + rtty_exit(rtty); + return; } - if (now - rtty->last_heartbeat > RTTY_HEARTBEAT_INTEVAL - 1) { - struct sysinfo info = {}; - - rtty->last_heartbeat = now; - - sysinfo(&info); - - buffer_put_u8(&rtty->wb, MSG_TYPE_HEARTBEAT); - buffer_put_u16be(&rtty->wb, 16); - buffer_put_u32be(&rtty->wb, info.uptime); - buffer_put_zero(&rtty->wb, 12); /* pad */ - ev_io_start(loop, &rtty->iow); - - log_debug("send msg: heartbeat\n"); + if (rtty->wait_heartbeat) { + log_err("heartbeat timeout\n"); + rtty_exit(rtty); + return; } + + sysinfo(&info); + + buffer_put_u8(&rtty->wb, MSG_TYPE_HEARTBEAT); + buffer_put_u16be(&rtty->wb, 16); + buffer_put_u32be(&rtty->wb, info.uptime); + buffer_put_zero(&rtty->wb, 12); /* pad */ + ev_io_start(loop, &rtty->iow); + + rtty->wait_heartbeat = true; + + ev_timer_set(&rtty->tmr, 0, RTTY_HEARTBEAT_TIMEOUT); + ev_timer_again(loop, &rtty->tmr); + + log_debug("send msg: heartbeat\n"); } int rtty_start(struct rtty *rtty) @@ -738,8 +748,7 @@ int rtty_start(struct rtty *rtty) rtty_run_state(RTTY_STATE_DISCONNECTED); - ev_timer_init(&rtty->tmr, rtty_timer_cb, 1.0, 1.0); - ev_timer_start(rtty->loop, &rtty->tmr); + ev_init(&rtty->tmr, rtty_timer_cb); if (tcp_connect(rtty->loop, rtty->host, rtty->port, on_net_connected, rtty) < 0 && !rtty->reconnect) @@ -748,8 +757,6 @@ int rtty_start(struct rtty *rtty) INIT_LIST_HEAD(&rtty->ttys); INIT_LIST_HEAD(&rtty->http_conns); - rtty->active = ev_now(rtty->loop); - return 0; } diff --git a/src/rtty.h b/src/rtty.h index d97c29a..9951eb2 100644 --- a/src/rtty.h +++ b/src/rtty.h @@ -37,9 +37,9 @@ #include "ssl/ssl.h" #endif -#define RTTY_PROTO_VER 4 +#define RTTY_PROTO_VER 5 #define RTTY_MAX_TTY 10 -#define RTTY_HEARTBEAT_INTEVAL 5.0 +#define RTTY_HEARTBEAT_TIMEOUT 3.0 #define RTTY_TTY_TIMEOUT 600 #define RTTY_TTY_ACK_BLOCK 4096 @@ -95,9 +95,9 @@ struct rtty { struct ev_io ior; struct ev_timer tmr; struct ev_loop *loop; - int ninactive; - ev_tstamp active; - ev_tstamp last_heartbeat; + ev_tstamp heartbeat; + bool wait_heartbeat; + bool registered; bool reconnect; #ifdef SSL_SUPPORT struct ssl_context *ssl_ctx;