use structured sending functions

This commit is contained in:
Eric Mertens 2023-11-26 15:32:52 -08:00
parent 52fe211067
commit b1d9bff111
7 changed files with 98 additions and 44 deletions

View File

@ -53,7 +53,7 @@ auto start(boost::asio::io_context & io, Settings const& settings) -> void
{ {
auto connection = std::make_shared<Connection>(io); auto connection = std::make_shared<Connection>(io);
watchdog_thread(connection.get()); watchdog_thread(*connection);
irc_parse_thread(connection.get()); irc_parse_thread(connection.get());
ping_thread(connection.get()); ping_thread(connection.get());
registration_thread(connection.get(), settings.password, settings.username, settings.realname, settings.nickname); registration_thread(connection.get(), settings.password, settings.username, settings.realname, settings.nickname);

View File

@ -10,7 +10,7 @@ auto ping_thread(Connection * connection) -> void
auto& irc = event.irc; auto& irc = event.irc;
if (IrcCommand::PING == event.command) if (IrcCommand::PING == event.command)
{ {
write_irc(*connection, "PONG", irc.args[0]); send_pong(*connection, irc.args[0]);
event.handled_ = true; event.handled_ = true;
} }
}); });

View File

@ -63,10 +63,10 @@ RegistrationThread::RegistrationThread(
auto RegistrationThread::on_connect() -> void auto RegistrationThread::on_connect() -> void
{ {
write_irc(*connection_, "CAP", "LS", "302"); send_cap_ls(*connection_);
write_irc(*connection_, "PASS", password_); send_pass(*connection_, password_);
write_irc(*connection_, "USER", username_, "*", "*", realname_); send_user(*connection_, username_, realname_);
write_irc(*connection_, "NICK", nickname_); send_nick(*connection_, nickname_);
connection_->remove_listener(connect_handle_); connection_->remove_listener(connect_handle_);
} }
@ -103,12 +103,12 @@ auto RegistrationThread::send_req() -> void
if (not outstanding.empty()) if (not outstanding.empty())
{ {
request.pop_back(); request.pop_back();
write_irc(*connection_, "CAP", "REQ", request); send_cap_req(*connection_, request);
stage_ = Stage::AckReply; stage_ = Stage::AckReply;
} }
else else
{ {
write_irc(*connection_, "CAP", "END"); send_cap_end(*connection_);
connection_->remove_listener(message_handle_); connection_->remove_listener(message_handle_);
} }
} }
@ -128,7 +128,7 @@ auto RegistrationThread::capack(IrcMsg const& msg) -> void
); );
if (outstanding.empty()) if (outstanding.empty())
{ {
write_irc(*connection_, "CAP", "END"); send_cap_end(*connection_);
connection_->remove_listener(message_handle_); connection_->remove_listener(message_handle_);
} }
} }

View File

@ -15,14 +15,14 @@ namespace {
struct WatchdogThread : std::enable_shared_from_this<WatchdogThread> struct WatchdogThread : std::enable_shared_from_this<WatchdogThread>
{ {
WatchdogThread(Connection * connection) WatchdogThread(Connection& connection)
: connection_{connection} : connection_{connection}
, timer_{connection->get_executor()} , timer_{connection.get_executor()}
, tried_ping{false} , tried_ping{false}
{ {
} }
Connection * connection_; Connection& connection_;
boost::asio::steady_timer timer_; boost::asio::steady_timer timer_;
bool tried_ping; bool tried_ping;
@ -50,11 +50,11 @@ struct WatchdogThread : std::enable_shared_from_this<WatchdogThread>
{ {
if (tried_ping) if (tried_ping)
{ {
connection_->close(); connection_.close();
} }
else else
{ {
write_irc(*connection_, "PING", "watchdog"); send_ping(connection_, "watchdog");
tried_ping = true; tried_ping = true;
timer_.expires_from_now(30s); timer_.expires_from_now(30s);
timer_.async_wait(timeout_token()); timer_.async_wait(timeout_token());
@ -75,18 +75,18 @@ struct WatchdogThread : std::enable_shared_from_this<WatchdogThread>
} // namespace } // namespace
auto watchdog_thread(Connection * connection) -> void auto watchdog_thread(Connection& connection) -> void
{ {
auto const thread = std::make_shared<WatchdogThread>(connection); auto const thread = std::make_shared<WatchdogThread>(connection);
connection->add_listener<ConnectEvent>([thread](auto&) connection.add_listener<ConnectEvent>([thread](auto&)
{ {
thread->on_connect(); thread->on_connect();
}); });
connection->add_listener<DisconnectEvent>([thread](auto&) connection.add_listener<DisconnectEvent>([thread](auto&)
{ {
thread->on_disconnect(); thread->on_disconnect();
}); });
connection->add_listener<IrcMsgEvent>([thread](auto&) connection.add_listener<IrcMsgEvent>([thread](auto&)
{ {
thread->on_activity(); thread->on_activity();
}); });

View File

@ -1,4 +1,4 @@
#pragma once #pragma once
class Connection; class Connection;
auto watchdog_thread(Connection * connection) -> void; auto watchdog_thread(Connection& connection) -> void;

View File

@ -1,18 +1,26 @@
#include "write_irc.hpp" #include "write_irc.hpp"
namespace {
auto write_irc(Connection& connection, std::string message) -> void auto write_irc(Connection& connection, std::string message) -> void
{ {
message += "\r\n"; message += "\r\n";
connection.write_raw(std::move(message)); connection.write_raw(std::move(message));
} }
auto is_invalid_last(char x) -> bool
{
return x == '\0' || x == '\r' || x == '\n';
}
auto is_invalid(char x) -> bool
{
return x == '\0' || x == '\r' || x == '\n' || x == ' ';
}
auto write_irc(Connection& connection, std::string front, std::string_view last) -> void auto write_irc(Connection& connection, std::string front, std::string_view last) -> void
{ {
auto const is_invalid = [](char x) -> bool { if (last.end() != std::find_if(last.begin(), last.end(), is_invalid_last))
return x == '\0' || x == '\r' || x == '\n';
};
if (last.end() != std::find_if(last.begin(), last.end(), is_invalid))
{ {
throw std::runtime_error{"bad irc argument"}; throw std::runtime_error{"bad irc argument"};
} }
@ -21,3 +29,61 @@ auto write_irc(Connection& connection, std::string front, std::string_view last)
front += last; front += last;
write_irc(connection, std::move(front)); write_irc(connection, std::move(front));
} }
template <typename... Args>
auto write_irc(Connection& connection, std::string front, std::string_view next, Args ...rest) -> void
{
if (next.empty()
|| next.front() == ':'
|| next.end() != std::find_if(next.begin(), next.end(), is_invalid))
{
throw std::runtime_error{"bad irc argument"};
}
front += " ";
front += next;
write_irc(connection, std::move(front), rest...);
}
} // namespace
auto send_ping(Connection& connection, std::string_view txt) -> void
{
write_irc(connection, "PING", txt);
}
auto send_pong(Connection& connection, std::string_view txt) -> void
{
write_irc(connection, "PONG", txt);
}
auto send_pass(Connection& connection, std::string_view password) -> void
{
write_irc(connection, "PASS", password);
}
auto send_user(Connection& connection, std::string_view user, std::string_view real) -> void
{
write_irc(connection, "USER", user, "*", "*", real);
}
auto send_nick(Connection& connection, std::string_view nick) -> void
{
write_irc(connection, "NICK", nick);
}
auto send_cap_ls(Connection& connection) -> void
{
write_irc(connection, "CAP", "LS", "302");
}
auto send_cap_end(Connection& connection) -> void
{
write_irc(connection, "CAP", "END");
}
auto send_cap_req(Connection& connection, std::string_view caps) -> void
{
write_irc(connection, "CAP", "REQ", caps);
}

View File

@ -2,23 +2,11 @@
#include "connection.hpp" #include "connection.hpp"
auto write_irc(Connection& connection, std::string message) -> void; auto send_ping(Connection&, std::string_view) -> void;
auto send_pong(Connection&, std::string_view) -> void;
auto write_irc(Connection& connection, std::string front, std::string_view last) -> void; auto send_pass(Connection&, std::string_view) -> void;
auto send_user(Connection&, std::string_view, std::string_view) -> void;
template <typename... Args> auto send_nick(Connection&, std::string_view) -> void;
auto write_irc(Connection& connection, std::string front, std::string_view next, Args ...rest) -> void auto send_cap_ls(Connection&) -> void;
{ auto send_cap_end(Connection&) -> void;
auto const is_invalid = [](char x) -> bool { auto send_cap_req(Connection&, std::string_view) -> void;
return x == '\0' || x == '\r' || x == '\n' || x == ' ';
};
if (next.empty() || next.end() != std::find_if(next.begin(), next.end(), is_invalid))
{
throw std::runtime_error{"bad irc argument"};
}
front += " ";
front += next;
write_irc(connection, std::move(front), rest...);
}