Mercurial > irccd
changeset 980:3afd375f308b
irccd: initial reconnection support
author | David Demelier <markand@malikania.fr> |
---|---|
date | Tue, 09 Feb 2021 21:34:00 +0100 |
parents | 489d80468925 |
children | e4fc051e2d94 |
files | irccd/conf.y lib/irccd/server.c lib/irccd/server.h |
diffstat | 3 files changed, 56 insertions(+), 14 deletions(-) [+] |
line wrap: on
line diff
--- a/irccd/conf.y Tue Feb 09 21:10:00 2021 +0100 +++ b/irccd/conf.y Tue Feb 09 21:34:00 2021 +0100 @@ -393,6 +393,8 @@ $$->flags |= IRC_SERVER_FLAGS_AUTO_REJOIN; else if (strcmp(s->value, "JOIN-INVITE") == 0) $$->flags |= IRC_SERVER_FLAGS_JOIN_INVITE; + else if (strcmp(s->value, "AUTO-RECONNECT") == 0) + $$->flags |= IRC_SERVER_FLAGS_AUTO_RECO; else errx(1, "invalid server option: %s", s->value); }
--- a/lib/irccd/server.c Tue Feb 09 21:10:00 2021 +0100 +++ b/lib/irccd/server.c Tue Feb 09 21:34:00 2021 +0100 @@ -39,6 +39,9 @@ #include "server.h" #include "util.h" +#define DELAY 30 /* Seconds to wait before reconnecting. */ +#define TIMEOUT 1800 /* Seconds before marking a server as dead. */ + static inline void clear_channels(struct irc_server *s, int free) { @@ -58,6 +61,8 @@ static inline void clear_server(struct irc_server *s) { + irc_conn_finish(&s->conn); + free(s->bufwhois.nickname); free(s->bufwhois.username); free(s->bufwhois.realname); @@ -170,6 +175,22 @@ } static void +fail(struct irc_server *s) +{ + clear_channels(s, 0); + clear_server(s); + + if (s->flags & IRC_SERVER_FLAGS_AUTO_RECO) { + irc_log_info("server %s: waiting %u seconds before reconnecting", s->name, DELAY); + s->state = IRC_SERVER_STATE_WAITING; + } else + s->state = IRC_SERVER_STATE_DISCONNECTED; + + /* Time point when we lose signal from the server. */ + s->lost_tp = time(NULL); +} + +static void handle_connect(struct irc_server *s, struct irc_event *ev, struct irc_conn_msg *msg) { (void)msg; @@ -189,10 +210,10 @@ static void handle_disconnect(struct irc_server *s, struct irc_event *ev) { - s->state = IRC_SERVER_STATE_NONE; ev->type = IRC_EVENT_DISCONNECT; ev->server = s; + fail(s); irc_log_info("server %s: connection lost", s->name); } @@ -402,7 +423,6 @@ static void handle_ping(struct irc_server *s, struct irc_event *ev, struct irc_conn_msg *msg) { - (void)s; (void)ev; (void)msg; @@ -554,6 +574,9 @@ { const struct handler *h; + /* Update last message time to detect non-notified disconnection. */ + s->last_tp = time(NULL); + if (!(h = find_handler(msg->cmd))) return; @@ -621,9 +644,16 @@ s->conn.flags |= IRC_CONN_SSL; if (irc_conn_connect(&s->conn) < 0) - s->state = IRC_SERVER_STATE_DISCONNECTED; + fail(s); else s->state = IRC_SERVER_STATE_CONNECTING; + + /* + * Assume the last time we received a message was now, so that + * irc_server_flush don't think the server is already dead while we + * didn't have any answer from it. + */ + s->last_tp = time(NULL); } void @@ -633,8 +663,6 @@ s->state = IRC_SERVER_STATE_DISCONNECTED; - irc_conn_disconnect(&s->conn); - clear_channels(s, 0); clear_server(s); } @@ -654,12 +682,18 @@ assert(s); assert(pfd); - if (irc_conn_flush(&s->conn, pfd) < 0) - return irc_server_disconnect(s); - if (s->conn.state != IRC_CONN_STATE_READY) - return; - switch (s->state) { + case IRC_SERVER_STATE_WAITING: + if (difftime(time(NULL), s->lost_tp) >= DELAY) + irc_server_connect(s); + break; + case IRC_SERVER_STATE_CONNECTED: + if (difftime(time(NULL), s->last_tp) >= TIMEOUT) { + irc_log_warn("server %s: no message in more than %u seconds", s->name, TIMEOUT); + fail(s); + } else if (irc_conn_flush(&s->conn, pfd) < 0) + return fail(s); + break; case IRC_SERVER_STATE_CONNECTING: /* * Now the conn object is ready which means the server has @@ -687,8 +721,11 @@ * this function is called again, we immediately change the state to * something else. */ - if (s->state == IRC_SERVER_STATE_DISCONNECTED) - return handle_disconnect(s, ev), 1; + if (s->state == IRC_SERVER_STATE_DISCONNECTED) { + handle_disconnect(s, ev); + s->state = IRC_SERVER_STATE_NONE; + return 1; + } if (irc_conn_poll(&s->conn, &msg)) return handle(s, ev, &msg), 1;
--- a/lib/irccd/server.h Tue Feb 09 21:10:00 2021 +0100 +++ b/lib/irccd/server.h Tue Feb 09 21:34:00 2021 +0100 @@ -21,6 +21,7 @@ #include <sys/queue.h> #include <stddef.h> +#include <time.h> #include "channel.h" #include "conn.h" @@ -44,8 +45,9 @@ IRC_SERVER_FLAGS_SSL = (1 << 0), IRC_SERVER_FLAGS_AUTO_REJOIN = (1 << 1), IRC_SERVER_FLAGS_JOIN_INVITE = (1 << 2), - IRC_SERVER_FLAGS_IPV4 = (1 << 3), - IRC_SERVER_FLAGS_IPV6 = (1 << 4) + IRC_SERVER_FLAGS_AUTO_RECO = (1 << 3), + IRC_SERVER_FLAGS_IPV4 = (1 << 4), + IRC_SERVER_FLAGS_IPV6 = (1 << 5) }; struct irc_server_user { @@ -88,6 +90,7 @@ struct irc_event_whois bufwhois; struct irc_conn conn; size_t refc; + time_t lost_tp, last_tp; LIST_ENTRY(irc_server) link; };