From 3da7c89b66ff04c84c31b0e275f5eea39ffe0766 Mon Sep 17 00:00:00 2001 From: deepend-tildeclub Date: Mon, 25 May 2026 11:43:10 -0600 Subject: [PATCH] Add configurable stale-link ping checks --- src/common/cfgfiles.c | 8 ++++++++ src/common/network.c | 27 +++++++++++++++++++++++++++ src/common/zoitechat.c | 13 +++++++------ src/common/zoitechat.h | 4 ++++ src/fe-gtk/setup.c | 6 ++++++ 5 files changed, 52 insertions(+), 6 deletions(-) diff --git a/src/common/cfgfiles.c b/src/common/cfgfiles.c index eff6d55c..c8fcf760 100644 --- a/src/common/cfgfiles.c +++ b/src/common/cfgfiles.c @@ -549,6 +549,10 @@ const struct prefs vars[] = #endif {"net_bind_host", P_OFFSET (hex_net_bind_host), TYPE_STR}, {"net_ping_timeout", P_OFFINT (hex_net_ping_timeout), TYPE_INT, zoitechat_reinit_timers}, + {"net_lag_check", P_OFFINT (hex_net_lag_check), TYPE_INT, zoitechat_reinit_timers}, + {"net_keepalive_idle", P_OFFINT (hex_net_keepalive_idle), TYPE_INT}, + {"net_keepalive_interval", P_OFFINT (hex_net_keepalive_interval), TYPE_INT}, + {"net_keepalive_count", P_OFFINT (hex_net_keepalive_count), TYPE_INT}, {"net_proxy_auth", P_OFFINT (hex_net_proxy_auth), TYPE_BOOL}, {"net_proxy_host", P_OFFSET (hex_net_proxy_host), TYPE_STR}, {"net_proxy_pass", P_OFFSET (hex_net_proxy_pass), TYPE_STR}, @@ -860,6 +864,10 @@ load_default_config(void) prefs.hex_irc_ban_type = 1; prefs.hex_irc_join_delay = 5; prefs.hex_net_ping_timeout = 60; + prefs.hex_net_lag_check = 60; + prefs.hex_net_keepalive_idle = 60; + prefs.hex_net_keepalive_interval = 20; + prefs.hex_net_keepalive_count = 3; prefs.hex_net_reconnect_delay = 10; prefs.hex_notify_timeout = 15; prefs.hex_text_max_indent = 256; diff --git a/src/common/network.c b/src/common/network.c index 60dc7e50..d821fb68 100644 --- a/src/common/network.c +++ b/src/common/network.c @@ -34,6 +34,9 @@ #ifndef WIN32 #include +#ifdef HAVE_NETINET_TCP_H +#include +#endif #endif #define WANTSOCKET @@ -43,6 +46,9 @@ #define NETWORK_PRIVATE #include "network.h" +#include "zoitechat.h" + +extern struct zoitechatprefs prefs; #define RAND_INT(n) ((int)(rand() / (RAND_MAX + 1.0) * (n))) @@ -58,6 +64,27 @@ net_set_socket_options (int sok) setsockopt (sok, SOL_SOCKET, SO_REUSEADDR, (char *) &sw, sizeof (sw)); sw = 1; setsockopt (sok, SOL_SOCKET, SO_KEEPALIVE, (char *) &sw, sizeof (sw)); +#ifdef TCP_KEEPIDLE + { + int keepidle = prefs.hex_net_keepalive_idle; + if (keepidle > 0) + setsockopt (sok, IPPROTO_TCP, TCP_KEEPIDLE, (char *) &keepidle, sizeof (keepidle)); + } +#endif +#ifdef TCP_KEEPINTVL + { + int keepintvl = prefs.hex_net_keepalive_interval; + if (keepintvl > 0) + setsockopt (sok, IPPROTO_TCP, TCP_KEEPINTVL, (char *) &keepintvl, sizeof (keepintvl)); + } +#endif +#ifdef TCP_KEEPCNT + { + int keepcnt = prefs.hex_net_keepalive_count; + if (keepcnt > 0) + setsockopt (sok, IPPROTO_TCP, TCP_KEEPCNT, (char *) &keepcnt, sizeof (keepcnt)); + } +#endif } char * diff --git a/src/common/zoitechat.c b/src/common/zoitechat.c index 4d8ca3fa..aba1c32e 100644 --- a/src/common/zoitechat.c +++ b/src/common/zoitechat.c @@ -379,6 +379,7 @@ lag_check (void) char tbuf[128]; time_t now = time (0); time_t lag; + time_t ping_age; tim = make_ping_time (); @@ -388,7 +389,7 @@ lag_check (void) if (serv->connected && serv->end_of_motd) { lag = now - serv->ping_recv; - if (prefs.hex_net_ping_timeout != 0 && lag > prefs.hex_net_ping_timeout && lag > 0) + if (serv->lag_sent && prefs.hex_net_ping_timeout != 0 && lag > prefs.hex_net_ping_timeout && lag > 0) { sprintf (tbuf, "%" G_GINT64_FORMAT, (gint64) lag); EMIT_SIGNAL (XP_TE_PINGTIMEOUT, serv->server_session, tbuf, NULL, @@ -398,11 +399,11 @@ lag_check (void) } else { - g_snprintf (tbuf, sizeof (tbuf), "LAG%lu", tim); - serv->p_ping (serv, "", tbuf); - - if (!serv->lag_sent) + ping_age = now - serv->ping_recv; + if (!serv->lag_sent && prefs.hex_net_lag_check > 0 && ping_age >= prefs.hex_net_lag_check) { + g_snprintf (tbuf, sizeof (tbuf), "LAG%lu", tim); + serv->p_ping (serv, "", tbuf); serv->lag_sent = tim; fe_set_lag (serv, -1); } @@ -525,7 +526,7 @@ zoitechat_reinit_timers (void) if ((prefs.hex_net_ping_timeout != 0 || prefs.hex_gui_lagometer) && lag_check_tag == 0) { - lag_check_tag = fe_timeout_add_seconds (30, zoitechat_lag_check, NULL); + lag_check_tag = fe_timeout_add_seconds (1, zoitechat_lag_check, NULL); } else if ((!prefs.hex_net_ping_timeout && !prefs.hex_gui_lagometer) && lag_check_tag != 0) diff --git a/src/common/zoitechat.h b/src/common/zoitechat.h index b67d1e70..6f8591c3 100644 --- a/src/common/zoitechat.h +++ b/src/common/zoitechat.h @@ -290,6 +290,10 @@ struct zoitechatprefs int hex_irc_join_delay; int hex_irc_notice_pos; int hex_net_ping_timeout; + int hex_net_lag_check; + int hex_net_keepalive_idle; + int hex_net_keepalive_interval; + int hex_net_keepalive_count; int hex_net_proxy_port; int hex_net_proxy_type; /* 0=disabled, 1=wingate 2=socks4, 3=socks5, 4=http */ int hex_net_proxy_use; /* 0=all 1=IRC_ONLY 2=DCC_ONLY */ diff --git a/src/fe-gtk/setup.c b/src/fe-gtk/setup.c index 3cca789a..d2dc0882 100644 --- a/src/fe-gtk/setup.c +++ b/src/fe-gtk/setup.c @@ -583,6 +583,7 @@ static const setting advanced_settings[] = {ST_TOGGLE, N_("Display lists in compact mode"), P_OFFINTNL(hex_gui_compact), N_("Use less spacing between user list/channel tree rows."), 0, 0}, {ST_TOGGLE, N_("Use server time if supported"), P_OFFINTNL(hex_irc_cap_server_time), N_("Display timestamps obtained from server if it supports the time-server extension."), 0, 0}, {ST_TOGGLE, N_("Automatically reconnect to servers on disconnect"), P_OFFINTNL(hex_net_auto_reconnect), 0, 0, 1}, + {ST_NUMBER, N_("Lag check interval:"), P_OFFINTNL(hex_net_lag_check), 0, (const char **)N_("seconds."), 9999}, {ST_NUMBER, N_("Auto reconnect delay:"), P_OFFINTNL(hex_net_reconnect_delay), 0, 0, 9999}, {ST_NUMBER, N_("Auto join delay:"), P_OFFINTNL(hex_irc_join_delay), 0, 0, 9999}, {ST_MENU, N_("Ban Type:"), P_OFFINTNL(hex_irc_ban_type), N_("Attempt to use this banmask when banning or quieting. (requires irc_who_join)"), bantypemenu, 0}, @@ -656,6 +657,11 @@ static const setting network_settings[] = {ST_MENU, N_("Type:"), P_OFFINTNL(hex_net_proxy_type), 0, proxytypes, 0}, {ST_MENU, N_("Use proxy for:"), P_OFFINTNL(hex_net_proxy_use), 0, proxyuse, 0}, + {ST_HEADER, N_("Connection Health"), 0, 0, 0, 0}, + {ST_NUMBER, N_("TCP keepalive idle:"), P_OFFINTNL(hex_net_keepalive_idle), 0, (const char **)N_("seconds."), 7200}, + {ST_NUMBER, N_("TCP keepalive interval:"), P_OFFINTNL(hex_net_keepalive_interval), 0, (const char **)N_("seconds."), 600}, + {ST_NUMBER, N_("TCP keepalive probes:"), P_OFFINTNL(hex_net_keepalive_count), 0, 0, 20}, + {ST_HEADER, N_("Proxy Authentication"), 0, 0, 0, 0}, {ST_TOGGLE, N_("Use authentication (HTTP or SOCKS5 only)"), P_OFFINTNL(hex_net_proxy_auth), 0, 0, 0}, {ST_ENTRY, N_("Username:"), P_OFFSETNL(hex_net_proxy_user), 0, 0, sizeof prefs.hex_net_proxy_user},