xbot/watchdog_thread.cpp
2023-11-25 20:09:20 -08:00

94 lines
1.9 KiB
C++

#include "watchdog_thread.hpp"
#include "connection.hpp"
#include "irc_parse_thread.hpp"
#include "write_irc.hpp"
#include <boost/asio/steady_timer.hpp>
#include <chrono>
#include <memory>
using namespace std::chrono_literals;
namespace {
struct WatchdogThread : std::enable_shared_from_this<WatchdogThread>
{
WatchdogThread(Connection * connection)
: connection_{connection}
, timer_{connection->get_executor()}
, tried_ping{false}
{
}
Connection * connection_;
boost::asio::steady_timer timer_;
bool tried_ping;
auto on_activity() -> void
{
tried_ping = false;
timer_.expires_from_now(30s);
}
auto timeout_token()
{
return [weak = weak_from_this()](auto const& error)
{
if (not error)
{
if (auto self = weak.lock())
{
self->on_timeout();
}
}
};
}
auto on_timeout() -> void
{
if (tried_ping)
{
connection_->close();
}
else
{
write_irc(*connection_, "PING", "watchdog");
tried_ping = true;
timer_.expires_from_now(30s);
timer_.async_wait(timeout_token());
}
}
auto on_connect() -> void
{
on_activity();
timer_.async_wait(timeout_token());
}
auto on_disconnect() -> void
{
timer_.cancel();
}
};
} // namespace
auto watchdog_thread(Connection * connection) -> void
{
auto const thread = std::make_shared<WatchdogThread>(connection);
connection->add_listener<ConnectEvent>([thread](auto&)
{
thread->on_connect();
});
connection->add_listener<DisconnectEvent>([thread](auto&)
{
thread->on_disconnect();
});
connection->add_listener<IrcMsgEvent>([thread](auto&)
{
thread->on_activity();
});
}