From 479da40a3da187cb659a436274d263583489dadd Mon Sep 17 00:00:00 2001 From: Přemysl Janouch Date: Sun, 10 Aug 2014 04:58:24 +0200 Subject: ZyklonB: add connection timeouts --- zyklonb.c | 39 +++++++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/zyklonb.c b/zyklonb.c index c99b141..d17bf7c 100644 --- a/zyklonb.c +++ b/zyklonb.c @@ -204,8 +204,6 @@ try_finish_quit (struct bot_context *ctx) static bool irc_send (struct bot_context *ctx, const char *format, ...) ATTRIBUTE_PRINTF (2, 3); -// XXX: is it okay to just ignore the return value and wait until we receive -// it in on_irc_readable()? static bool irc_send (struct bot_context *ctx, const char *format, ...) { @@ -1469,6 +1467,36 @@ on_irc_disconnected (struct bot_context *ctx) irc_try_reconnect (ctx); } +static void +on_irc_ping_timeout (void *user_data) +{ + struct bot_context *ctx = user_data; + print_error ("connection timeout"); + on_irc_disconnected (ctx); +} + +static void +on_irc_timeout (void *user_data) +{ + // Provoke a response from the server + struct bot_context *ctx = user_data; + irc_send (ctx, "PING :%s", str_map_find (&ctx->config, "nickname")); +} + +static void +irc_reset_timeouts (struct bot_context *ctx) +{ + ssize_t i; + struct poller_timers *timers = &ctx->poller.timers; + while ((i = poller_timers_find_by_data (timers, ctx)) != -1) + poller_timers_remove_at_index (timers, i); + + poller_timers_add (&ctx->poller.timers, + on_irc_timeout, ctx, 3 * 60 * 1000); + poller_timers_add (&ctx->poller.timers, + on_irc_ping_timeout, ctx, (3 * 60 + 30) * 1000); +} + static void on_irc_readable (const struct pollfd *fd, struct bot_context *ctx) { @@ -1515,6 +1543,8 @@ end: if (disconnected) on_irc_disconnected (ctx); + else + irc_reset_timeouts (ctx); } static bool @@ -1550,16 +1580,13 @@ irc_connect (struct bot_context *ctx, struct error **e) if (!irc_establish_connection (ctx, irc_host, irc_port, use_ssl, e)) return false; - // TODO: set a timeout on the socket, something like 30 minutes, then we - // should ideally send a PING... or just forcefully reconnect. - // // TODO: in exec try: 1/ set blocking, 2/ setsockopt() SO_LINGER, // (struct linger) { .l_onoff = true; .l_linger = 1 /* 1s should do */; } // 3/ /* O_CLOEXEC */ But only if the QUIT message proves unreliable. poller_set (&ctx->poller, ctx->irc_fd, POLLIN, (poller_dispatcher_func) on_irc_readable, ctx); + irc_reset_timeouts (ctx); - // TODO: probably check for errors from these calls as well irc_send (ctx, "NICK %s", nickname); irc_send (ctx, "USER %s 8 * :%s", username, realname); return true; -- cgit v1.2.3-70-g09d2