From 2b6c5833bb6cd6b1e21bb66a0ebbc6a6e3e86767 Mon Sep 17 00:00:00 2001 From: Adam Date: Thu, 22 Jun 2017 17:59:58 -0400 Subject: Ping uplink occasionally and disconnect if no pong is received --- include/modules/protocol/rfc1459.h | 8 ++++++++ include/uplink.h | 12 ++++++++++- modules/protocol/bahamut.cpp | 2 ++ modules/protocol/inspircd20.cpp | 2 ++ modules/protocol/plexus.cpp | 2 ++ modules/protocol/rfc1459.cpp | 6 ++++++ src/main.cpp | 1 + src/uplink.cpp | 42 ++++++++++++++++++++++++++++++++++++-- 8 files changed, 72 insertions(+), 3 deletions(-) diff --git a/include/modules/protocol/rfc1459.h b/include/modules/protocol/rfc1459.h index 54c4bada5..8780892e0 100644 --- a/include/modules/protocol/rfc1459.h +++ b/include/modules/protocol/rfc1459.h @@ -288,6 +288,14 @@ class Ping : public IRCDMessage void Run(MessageSource &source, const std::vector ¶ms) override; }; +class Pong : public IRCDMessage +{ + public: + Pong(Module *creator, const Anope::string &mname = "PONG") : IRCDMessage(creator, mname) { } + + void Run(MessageSource &source, const std::vector ¶ms) override; +}; + class Privmsg : public IRCDMessage { public: diff --git a/include/uplink.h b/include/uplink.h index 8cb8c8b20..be2675931 100644 --- a/include/uplink.h +++ b/include/uplink.h @@ -21,6 +21,7 @@ #include "sockets.h" #include "protocol.h" +#include "timers.h" namespace Uplink { @@ -40,13 +41,22 @@ namespace Uplink IRCMessage message(Me, command, std::forward(args)...); SendMessage(message); } + + class PingTimer : public Timer + { + public: + PingTimer(time_t); + void Tick(time_t) override; + }; } /* This is the socket to our uplink */ class UplinkSocket : public ConnectionSocket, public BufferedSocket { public: - bool error; + bool error = false; + time_t last_read = 0; + bool pinged = false; UplinkSocket(); ~UplinkSocket(); bool ProcessRead() override; diff --git a/modules/protocol/bahamut.cpp b/modules/protocol/bahamut.cpp index 045045d03..fa41ebc39 100644 --- a/modules/protocol/bahamut.cpp +++ b/modules/protocol/bahamut.cpp @@ -488,6 +488,7 @@ class ProtoBahamut : public Module rfc1459::Notice message_notice; rfc1459::Part message_part; rfc1459::Ping message_ping; + rfc1459::Pong message_pong; rfc1459::Privmsg message_privmsg; rfc1459::Quit message_quit; rfc1459::SQuit message_squit; @@ -558,6 +559,7 @@ class ProtoBahamut : public Module , message_notice(this) , message_part(this) , message_ping(this) + , message_pong(this) , message_privmsg(this) , message_quit(this) , message_squit(this) diff --git a/modules/protocol/inspircd20.cpp b/modules/protocol/inspircd20.cpp index 14040d98e..96ada4666 100644 --- a/modules/protocol/inspircd20.cpp +++ b/modules/protocol/inspircd20.cpp @@ -1271,6 +1271,7 @@ class ProtoInspIRCd20 : public Module rfc1459::Notice message_notice; rfc1459::Part message_part; rfc1459::Ping message_ping; + rfc1459::Pong message_pong; rfc1459::Privmsg message_privmsg; rfc1459::Quit message_quit; rfc1459::Stats message_stats; @@ -1370,6 +1371,7 @@ class ProtoInspIRCd20 : public Module , message_notice(this) , message_part(this) , message_ping(this) + , message_pong(this) , message_privmsg(this) , message_quit(this) , message_stats(this) diff --git a/modules/protocol/plexus.cpp b/modules/protocol/plexus.cpp index 98654119f..5743ef50e 100644 --- a/modules/protocol/plexus.cpp +++ b/modules/protocol/plexus.cpp @@ -280,6 +280,7 @@ class ProtoPlexus : public Module rfc1459::Notice message_notice; rfc1459::Part message_part; rfc1459::Ping message_ping; + rfc1459::Pong message_pong; rfc1459::Privmsg message_privmsg; rfc1459::Quit message_quit; rfc1459::SQuit message_squit; @@ -359,6 +360,7 @@ class ProtoPlexus : public Module , message_notice(this) , message_part(this) , message_ping(this) + , message_pong(this) , message_privmsg(this) , message_quit(this) , message_squit(this) diff --git a/modules/protocol/rfc1459.cpp b/modules/protocol/rfc1459.cpp index eee93571a..77f3dedc3 100644 --- a/modules/protocol/rfc1459.cpp +++ b/modules/protocol/rfc1459.cpp @@ -444,6 +444,12 @@ void Ping::Run(MessageSource &source, const std::vector ¶ms) IRCD->Send(params.size() > 1 ? params[1] : Me->GetSID(), params[0]); } +void Pong::Run(MessageSource &source, const std::vector ¶ms) +{ + // Here to get rid of the "unknown command from server" + // Read timeout is reset on any uplink recv() +} + void Privmsg::Run(MessageSource &source, const std::vector ¶ms) { const Anope::string &receiver = params[0]; diff --git a/src/main.cpp b/src/main.cpp index ca67ec56e..34f2a2797 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -145,6 +145,7 @@ int main(int ac, char **av, char **envp) /* Set up timers */ time_t last_check = Anope::CurTime; ExpireTimer expireTimer(Config->GetBlock("options")->Get("expiretimeout", "30m")); + Uplink::PingTimer pingTimer(30); /*** Main loop. ***/ while (!Anope::Quitting) diff --git a/src/uplink.cpp b/src/uplink.cpp index fb5f3ec23..bd069843c 100644 --- a/src/uplink.cpp +++ b/src/uplink.cpp @@ -42,11 +42,47 @@ class ReconnectTimer : public Timer } catch (const SocketException &ex) { - Anope::Logger.Terminal(_("Unable to connect to uplink #{0} ({1}:{2}): {3}"), Anope::CurrentUplink + 1, Config->Uplinks[Anope::CurrentUplink].host, Config->Uplinks[Anope::CurrentUplink].port, ex.GetReason()); + Anope::Logger.Terminal(_("Unable to connect to uplink #{0} ({1}:{2}): {3}"), + Anope::CurrentUplink + 1, Config->Uplinks[Anope::CurrentUplink].host, + Config->Uplinks[Anope::CurrentUplink].port, ex.GetReason()); } } }; +Uplink::PingTimer::PingTimer(time_t timeout) : Timer(timeout, Anope::CurTime, true) +{ +} + +void Uplink::PingTimer::Tick(time_t) +{ + Server *uplink; + time_t ping_time = Config->GetBlock("options")->Get("ping_time", "60"); + + if (!UplinkSock || Anope::CurTime - UplinkSock->last_read <= ping_time) + return; + + if (Me->GetLinks().empty()) + return; + + if (UplinkSock->pinged) + { + Anope::Logger.Log(_("No response from uplink in {0} seconds, disconnecting"), ping_time); + + UplinkSock->error = true; + Anope::QuitReason = "Ping timeout"; + delete UplinkSock; + Anope::QuitReason.clear(); + return; + } + + Anope::Logger.Debug("Pinging uplink"); + + uplink = Me->GetLinks().front(); + UplinkSock->pinged = true; + + IRCD->Send(Me->GetName(), uplink->GetName()); +} + void Uplink::Connect() { if (Config->Uplinks.empty()) @@ -71,7 +107,6 @@ void Uplink::Connect() UplinkSocket::UplinkSocket() : Socket(-1, Config->Uplinks[Anope::CurrentUplink].ipv6), ConnectionSocket(), BufferedSocket() { - error = false; UplinkSock = this; } @@ -142,6 +177,9 @@ UplinkSocket::~UplinkSocket() bool UplinkSocket::ProcessRead() { + last_read = Anope::CurTime; + pinged = false; + bool b = BufferedSocket::ProcessRead(); for (Anope::string buf; (buf = this->GetLine()).empty() == false;) { -- cgit