use shared-ptr more consistently
This commit is contained in:
parent
eb01b304e3
commit
7728bc6aee
@ -23,23 +23,26 @@ using namespace std::literals;
|
||||
|
||||
static auto start(boost::asio::io_context &io, const Settings &settings) -> void
|
||||
{
|
||||
Ref<X509> cert;
|
||||
if (settings.use_tls && not settings.tls_certfile.empty())
|
||||
Ref<X509> tls_cert;
|
||||
if (settings.use_tls && not settings.tls_cert_file.empty())
|
||||
{
|
||||
cert = cert_from_file(settings.tls_certfile);
|
||||
tls_cert = cert_from_file(settings.tls_cert_file);
|
||||
}
|
||||
|
||||
Ref<EVP_PKEY> key;
|
||||
if (settings.use_tls && not settings.tls_keyfile.empty())
|
||||
Ref<EVP_PKEY> tls_key;
|
||||
if (settings.use_tls && not settings.tls_key_file.empty())
|
||||
{
|
||||
key = key_from_file(settings.tls_keyfile, "");
|
||||
tls_key = key_from_file(settings.tls_key_file, settings.tls_key_password);
|
||||
}
|
||||
|
||||
Ref<EVP_PKEY> sasl_key;
|
||||
if (not settings.sasl_key_file.empty())
|
||||
{
|
||||
sasl_key = key_from_file(settings.sasl_key_file, settings.sasl_key_password);
|
||||
}
|
||||
|
||||
const auto connection = std::make_shared<Connection>(io);
|
||||
const auto client = Client::start(*connection);
|
||||
Ref<EVP_PKEY> sasl_key;
|
||||
if (not settings.sasl_key_file.empty())
|
||||
sasl_key = key_from_file(settings.sasl_key_file, settings.sasl_key_password);
|
||||
const auto client = Client::start(connection);
|
||||
Registration::start({
|
||||
.nickname = settings.nickname,
|
||||
.realname = settings.realname,
|
||||
@ -51,32 +54,33 @@ static auto start(boost::asio::io_context &io, const Settings &settings) -> void
|
||||
.sasl_password = settings.sasl_password,
|
||||
.sasl_key = std::move(sasl_key),
|
||||
}, client);
|
||||
|
||||
const auto bot = Bot::start(client);
|
||||
|
||||
// Configure CHALLENGE on registration if applicable
|
||||
if (not settings.challenge_username.empty() && not settings.challenge_key_file.empty()) {
|
||||
if (auto key = key_from_file(settings.challenge_key_file, settings.challenge_key_password)) {
|
||||
client->sig_registered.connect([&settings, connection, key = std::move(key)]() {
|
||||
Challenge::start(*connection, settings.challenge_username, key);
|
||||
Challenge::start(connection, settings.challenge_username, key);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// On disconnect tear down the various layers and reconnect in 5 seconds
|
||||
// connection is captured in the disconnect handler so it can keep itself alive
|
||||
connection->sig_disconnect.connect(
|
||||
[&io, &settings, client, bot]() {
|
||||
client->shutdown();
|
||||
bot->shutdown();
|
||||
|
||||
[&io, &settings, connection]() {
|
||||
auto timer = std::make_shared<boost::asio::steady_timer>(io);
|
||||
timer->expires_after(5s);
|
||||
timer->async_wait([&io, &settings, timer](auto) { start(io, settings); });
|
||||
}
|
||||
);
|
||||
|
||||
bot->sig_command.connect([connection](auto &cmd) {
|
||||
std::cout << "COMMAND " << cmd.command << " from " << cmd.account << std::endl;
|
||||
// Simple example of a command handler
|
||||
bot->sig_command.connect([connection](const Bot::Command &cmd) {
|
||||
if (cmd.oper == "glguy" && cmd.command == "ping") {
|
||||
connection->send_notice("glguy", cmd.arguments);
|
||||
if (auto bang = cmd.source.find('!'); bang != cmd.source.npos) {
|
||||
connection->send_notice(cmd.source.substr(0, bang), cmd.arguments);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -85,12 +89,12 @@ static auto start(boost::asio::io_context &io, const Settings &settings) -> void
|
||||
.host = settings.host,
|
||||
.port = settings.service,
|
||||
.verify = settings.tls_hostname,
|
||||
.client_cert = std::move(cert),
|
||||
.client_key = std::move(key),
|
||||
.client_cert = std::move(tls_cert),
|
||||
.client_key = std::move(tls_key),
|
||||
});
|
||||
}
|
||||
|
||||
static auto get_settings(const char *filename) -> Settings
|
||||
static auto get_settings(const char * const filename) -> Settings
|
||||
{
|
||||
if (auto config_stream = std::ifstream{filename})
|
||||
{
|
||||
|
@ -20,11 +20,12 @@ auto Settings::from_stream(std::istream &in) -> Settings
|
||||
.sasl_key_file = config["sasl_key_file"].value_or(std::string{}),
|
||||
.sasl_key_password = config["sasl_key_password"].value_or(std::string{}),
|
||||
.tls_hostname = config["tls_hostname"].value_or(std::string{}),
|
||||
.tls_certfile = config["tls_certfile"].value_or(std::string{}),
|
||||
.tls_keyfile = config["tls_keyfile"].value_or(std::string{}),
|
||||
. challenge_username = config["challenge_username"].value_or(std::string{}),
|
||||
. challenge_key_file = config["challenge_key_file"].value_or(std::string{}),
|
||||
. challenge_key_password = config["challenge_key_password"].value_or(std::string{}),
|
||||
.tls_cert_file = config["tls_cert_file"].value_or(std::string{}),
|
||||
.tls_key_file = config["tls_key_file"].value_or(std::string{}),
|
||||
.tls_key_password = config["tls_key_password"].value_or(std::string{}),
|
||||
.challenge_username = config["challenge_username"].value_or(std::string{}),
|
||||
.challenge_key_file = config["challenge_key_file"].value_or(std::string{}),
|
||||
.challenge_key_password = config["challenge_key_password"].value_or(std::string{}),
|
||||
.use_tls = config["use_tls"].value_or(false),
|
||||
};
|
||||
}
|
||||
|
@ -20,8 +20,9 @@ struct Settings
|
||||
std::string sasl_key_password;
|
||||
|
||||
std::string tls_hostname;
|
||||
std::string tls_certfile;
|
||||
std::string tls_keyfile;
|
||||
std::string tls_cert_file;
|
||||
std::string tls_key_file;
|
||||
std::string tls_key_password;
|
||||
|
||||
std::string challenge_username;
|
||||
std::string challenge_key_file;
|
||||
|
@ -12,9 +12,9 @@
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
Challenge::Challenge(Ref<EVP_PKEY> key, Connection & connection)
|
||||
Challenge::Challenge(Ref<EVP_PKEY> key, std::shared_ptr<Connection> connection)
|
||||
: key_{std::move(key)}
|
||||
, connection_{connection}
|
||||
, connection_{std::move(connection)}
|
||||
{}
|
||||
|
||||
auto Challenge::on_ircmsg(IrcCommand cmd, const IrcMsg &msg) -> void {
|
||||
@ -29,7 +29,7 @@ auto Challenge::on_ircmsg(IrcCommand cmd, const IrcMsg &msg) -> void {
|
||||
break;
|
||||
case IrcCommand::RPL_YOUREOPER:
|
||||
slot_.disconnect();
|
||||
connection_.send_ping("mitigation");
|
||||
connection_->send_ping("mitigation");
|
||||
break;
|
||||
case IrcCommand::RPL_ENDOFRSACHALLENGE2:
|
||||
finish_challenge();
|
||||
@ -78,14 +78,14 @@ auto Challenge::finish_challenge() -> void
|
||||
buffer_[0] = '+';
|
||||
mybase64::encode(std::string_view{(char*)digest, digestlen}, buffer_.data() + 1);
|
||||
|
||||
connection_.send_challenge(buffer_);
|
||||
connection_->send_challenge(buffer_);
|
||||
buffer_.clear();
|
||||
}
|
||||
|
||||
auto Challenge::start(Connection &connection, const std::string_view user, Ref<EVP_PKEY> ref) -> std::shared_ptr<Challenge>
|
||||
auto Challenge::start(std::shared_ptr<Connection> connection, const std::string_view user, Ref<EVP_PKEY> ref) -> std::shared_ptr<Challenge>
|
||||
{
|
||||
auto self = std::make_shared<Challenge>(std::move(ref), connection);
|
||||
self->slot_ = connection.sig_ircmsg.connect([self](auto cmd, auto &msg) { self->on_ircmsg(cmd, msg); });
|
||||
connection.send_challenge(user);
|
||||
self->slot_ = connection->sig_ircmsg.connect([self](auto cmd, auto &msg) { self->on_ircmsg(cmd, msg); });
|
||||
connection->send_challenge(user);
|
||||
return self;
|
||||
}
|
||||
|
@ -137,11 +137,11 @@ auto Client::on_chat(bool notice, const IrcMsg &irc) -> void
|
||||
});
|
||||
}
|
||||
|
||||
auto Client::start(Connection &connection) -> std::shared_ptr<Client>
|
||||
auto Client::start(std::shared_ptr<Connection> connection) -> std::shared_ptr<Client>
|
||||
{
|
||||
auto thread = std::make_shared<Client>(connection);
|
||||
|
||||
connection.sig_ircmsg.connect([thread](auto cmd, auto &msg) {
|
||||
connection->sig_ircmsg.connect([thread](auto cmd, auto &msg) {
|
||||
switch (cmd)
|
||||
{
|
||||
case IrcCommand::PRIVMSG:
|
||||
@ -186,7 +186,7 @@ auto Client::start(Connection &connection) -> std::shared_ptr<Client>
|
||||
}
|
||||
});
|
||||
|
||||
connection.sig_authenticate.connect([thread](auto msg) {
|
||||
connection->sig_authenticate.connect([thread](auto msg) {
|
||||
thread->on_authenticate(msg);
|
||||
});
|
||||
|
||||
@ -239,20 +239,20 @@ auto Client::on_authenticate(const std::string_view body) -> void
|
||||
if (not sasl_mechanism_)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(warning) << "Unexpected AUTHENTICATE from server"sv;
|
||||
connection_.send_authenticate_abort();
|
||||
connection_->send_authenticate_abort();
|
||||
return;
|
||||
}
|
||||
|
||||
std::visit(
|
||||
overloaded{
|
||||
[this](const std::string &reply) {
|
||||
connection_.send_authenticate_encoded(reply);
|
||||
connection_->send_authenticate_encoded(reply);
|
||||
},
|
||||
[this](SaslMechanism::NoReply) {
|
||||
connection_.send_authenticate("*"sv);
|
||||
connection_->send_authenticate("*"sv);
|
||||
},
|
||||
[this](SaslMechanism::Failure) {
|
||||
connection_.send_authenticate_abort();
|
||||
connection_->send_authenticate_abort();
|
||||
},
|
||||
},
|
||||
sasl_mechanism_->step(body));
|
||||
@ -267,11 +267,11 @@ auto Client::start_sasl(std::unique_ptr<SaslMechanism> mechanism) -> void
|
||||
{
|
||||
if (sasl_mechanism_)
|
||||
{
|
||||
connection_.send_authenticate("*"sv); // abort SASL
|
||||
connection_->send_authenticate("*"sv); // abort SASL
|
||||
}
|
||||
|
||||
sasl_mechanism_ = std::move(mechanism);
|
||||
connection_.send_authenticate(sasl_mechanism_->mechanism_name());
|
||||
connection_->send_authenticate(sasl_mechanism_->mechanism_name());
|
||||
}
|
||||
|
||||
static auto tolower_rfc1459(int c) -> int
|
||||
@ -328,16 +328,10 @@ auto Client::casemap_compare(std::string_view lhs, std::string_view rhs) const -
|
||||
}
|
||||
}
|
||||
|
||||
auto Client::shutdown() -> void
|
||||
{
|
||||
sig_registered.disconnect_all_slots();
|
||||
sig_cap_ls.disconnect_all_slots();
|
||||
}
|
||||
|
||||
auto Client::list_caps() -> void
|
||||
{
|
||||
caps_available_.clear();
|
||||
connection_.send_cap_ls();
|
||||
connection_->send_cap_ls();
|
||||
}
|
||||
|
||||
auto Client::on_cap(const IrcMsg &msg) -> void
|
||||
|
@ -556,13 +556,13 @@ auto Connection::start(Settings settings) -> void
|
||||
BOOST_LOG_TRIVIAL(debug) << "TERMINATED: " << e.what();
|
||||
}
|
||||
|
||||
self->sig_disconnect();
|
||||
|
||||
// Disconnect all slots to avoid circular references
|
||||
self->sig_connect.disconnect_all_slots();
|
||||
self->sig_ircmsg.disconnect_all_slots();
|
||||
self->sig_disconnect.disconnect_all_slots();
|
||||
self->sig_snote.disconnect_all_slots();
|
||||
self->sig_authenticate.disconnect_all_slots();
|
||||
|
||||
self->sig_disconnect();
|
||||
self->sig_disconnect.disconnect_all_slots();
|
||||
});
|
||||
}
|
||||
|
@ -12,7 +12,7 @@
|
||||
class Challenge : std::enable_shared_from_this<Challenge>
|
||||
{
|
||||
Ref<EVP_PKEY> key_;
|
||||
Connection &connection_;
|
||||
std::shared_ptr<Connection> connection_;
|
||||
boost::signals2::scoped_connection slot_;
|
||||
std::string buffer_;
|
||||
|
||||
@ -20,12 +20,12 @@ class Challenge : std::enable_shared_from_this<Challenge>
|
||||
auto finish_challenge() -> void;
|
||||
|
||||
public:
|
||||
Challenge(Ref<EVP_PKEY>, Connection &);
|
||||
Challenge(Ref<EVP_PKEY>, std::shared_ptr<Connection>);
|
||||
|
||||
/// @brief Starts the CHALLENGE protocol.
|
||||
/// @param connection Registered connection.
|
||||
/// @param user Operator username
|
||||
/// @param key Operator private RSA key
|
||||
/// @return Handle to the challenge object.
|
||||
static auto start(Connection &, std::string_view user, Ref<EVP_PKEY> key) -> std::shared_ptr<Challenge>;
|
||||
static auto start(std::shared_ptr<Connection>, std::string_view user, Ref<EVP_PKEY> key) -> std::shared_ptr<Challenge>;
|
||||
};
|
||||
|
@ -32,7 +32,7 @@ struct Chat {
|
||||
*/
|
||||
class Client
|
||||
{
|
||||
Connection &connection_;
|
||||
std::shared_ptr<Connection> connection_;
|
||||
|
||||
std::string nickname_;
|
||||
std::string mode_;
|
||||
@ -67,23 +67,23 @@ public:
|
||||
boost::signals2::signal<void(const std::unordered_map<std::string, std::string> &)> sig_cap_ls;
|
||||
boost::signals2::signal<void(const Chat &)> sig_chat;
|
||||
|
||||
Client(Connection &connection)
|
||||
: connection_{connection}
|
||||
Client(std::shared_ptr<Connection> connection)
|
||||
: connection_{std::move(connection)}
|
||||
, casemap_{Casemap::Rfc1459}
|
||||
, channel_prefix_{"#&"}
|
||||
, status_msg_{"+@"}
|
||||
{
|
||||
}
|
||||
|
||||
auto get_connection() -> Connection & { return connection_; }
|
||||
auto get_connection() -> Connection & { return *connection_; }
|
||||
|
||||
static auto start(Connection &) -> std::shared_ptr<Client>;
|
||||
static auto start(std::shared_ptr<Connection>) -> std::shared_ptr<Client>;
|
||||
|
||||
auto start_sasl(std::unique_ptr<SaslMechanism> mechanism) -> void;
|
||||
|
||||
auto get_connection() const -> std::shared_ptr<Connection>
|
||||
{
|
||||
return connection_.shared_from_this();
|
||||
return connection_->shared_from_this();
|
||||
}
|
||||
|
||||
auto get_my_nick() const -> const std::string &;
|
||||
|
Loading…
x
Reference in New Issue
Block a user