consolidate more logic into Connection
This commit is contained in:
parent
553d261d73
commit
37721092db
@ -31,10 +31,8 @@ add_subdirectory(mybase64)
|
|||||||
|
|
||||||
add_executable(xbot
|
add_executable(xbot
|
||||||
main.cpp irc_commands.inc ircmsg.cpp settings.cpp connection.cpp
|
main.cpp irc_commands.inc ircmsg.cpp settings.cpp connection.cpp
|
||||||
write_irc.cpp
|
|
||||||
registration_thread.cpp
|
registration_thread.cpp
|
||||||
ping_thread.cpp
|
snote.cpp
|
||||||
snote_thread.cpp
|
|
||||||
self_thread.cpp
|
self_thread.cpp
|
||||||
irc_coroutine.cpp
|
irc_coroutine.cpp
|
||||||
watchdog_thread.cpp
|
watchdog_thread.cpp
|
||||||
|
108
connection.cpp
108
connection.cpp
@ -79,7 +79,9 @@ auto Connection::connect(
|
|||||||
sig_connect();
|
sig_connect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Start the queue writer after connection
|
||||||
self->writer();
|
self->writer();
|
||||||
|
|
||||||
for(LineBuffer buffer{32'768};;)
|
for(LineBuffer buffer{32'768};;)
|
||||||
{
|
{
|
||||||
boost::system::error_code error;
|
boost::system::error_code error;
|
||||||
@ -108,11 +110,33 @@ auto Connection::dispatch_line(char *line) -> void
|
|||||||
&& recognized->max_args >= msg.args.size()
|
&& recognized->max_args >= msg.args.size()
|
||||||
? recognized->command : IrcCommand::UNKNOWN;
|
? recognized->command : IrcCommand::UNKNOWN;
|
||||||
|
|
||||||
if (IrcCommand::UNKNOWN == command)
|
switch (command) {
|
||||||
{
|
|
||||||
|
// Respond to pings immediate and discard
|
||||||
|
case IrcCommand::PING:
|
||||||
|
send_pong(msg.args[0]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Unknown message generate warnings but do not dispatch
|
||||||
|
// Messages can be unknown due to bad command or bad argument count
|
||||||
|
case IrcCommand::UNKNOWN:
|
||||||
BOOST_LOG_TRIVIAL(warning) << "Unrecognized command: " << msg.command << " " << msg.args.size();
|
BOOST_LOG_TRIVIAL(warning) << "Unrecognized command: " << msg.command << " " << msg.args.size();
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Server notice generate snote events but not IRC command events
|
||||||
|
case IrcCommand::NOTICE:
|
||||||
|
if (auto match = snoteCore.match(msg)) {
|
||||||
|
sig_snote(match->first, match->second);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* FALLTHROUGH */
|
||||||
|
|
||||||
|
// Normal IRC commands
|
||||||
|
default:
|
||||||
|
sig_ircmsg(command, msg);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
sig_ircmsg(command, msg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Connection::write_line(std::string message) -> void
|
auto Connection::write_line(std::string message) -> void
|
||||||
@ -131,3 +155,81 @@ auto Connection::close() -> void
|
|||||||
{
|
{
|
||||||
stream_.close();
|
stream_.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
auto is_invalid_last(char x) -> bool
|
||||||
|
{
|
||||||
|
return x == '\0' || x == '\r' || x == '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Connection::write_irc(std::string message) -> void
|
||||||
|
{
|
||||||
|
write_line(std::move(message));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Connection::write_irc(std::string front, std::string_view last) -> void
|
||||||
|
{
|
||||||
|
if (last.end() != std::find_if(last.begin(), last.end(), is_invalid_last))
|
||||||
|
{
|
||||||
|
throw std::runtime_error{"bad irc argument"};
|
||||||
|
}
|
||||||
|
|
||||||
|
front += " :";
|
||||||
|
front += last;
|
||||||
|
write_irc(std::move(front));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Connection::send_ping(std::string_view txt) -> void
|
||||||
|
{
|
||||||
|
write_irc("PING", txt);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Connection::send_pong(std::string_view txt) -> void
|
||||||
|
{
|
||||||
|
write_irc("PONG", txt);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Connection::send_pass(std::string_view password) -> void
|
||||||
|
{
|
||||||
|
write_irc("PASS", password);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Connection::send_user(std::string_view user, std::string_view real) -> void
|
||||||
|
{
|
||||||
|
write_irc("USER", user, "*", "*", real);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Connection::send_nick(std::string_view nick) -> void
|
||||||
|
{
|
||||||
|
write_irc("NICK", nick);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Connection::send_cap_ls() -> void
|
||||||
|
{
|
||||||
|
write_irc("CAP", "LS", "302");
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Connection::send_cap_end() -> void
|
||||||
|
{
|
||||||
|
write_irc("CAP", "END");
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Connection::send_cap_req(std::string_view caps) -> void
|
||||||
|
{
|
||||||
|
write_irc("CAP", "REQ", caps);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Connection::send_privmsg(std::string_view target, std::string_view message) -> void
|
||||||
|
{
|
||||||
|
write_irc("PRIVMSG", target, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Connection::send_notice(std::string_view target, std::string_view message) -> void
|
||||||
|
{
|
||||||
|
write_irc("NOTICE", target, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Connection::send_authenticate(std::string_view message) -> void
|
||||||
|
{
|
||||||
|
write_irc("AUTHENTICATE", message);
|
||||||
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "ircmsg.hpp"
|
#include "ircmsg.hpp"
|
||||||
#include "irc_command.hpp"
|
#include "irc_command.hpp"
|
||||||
|
#include "snote.hpp"
|
||||||
|
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
#include <boost/signals2.hpp>
|
#include <boost/signals2.hpp>
|
||||||
@ -21,20 +22,27 @@ private:
|
|||||||
auto writer_immediate() -> void;
|
auto writer_immediate() -> void;
|
||||||
auto dispatch_line(char * line) -> void;
|
auto dispatch_line(char * line) -> void;
|
||||||
|
|
||||||
|
/// Write bytes into the socket. Messages should be properly newline terminated.
|
||||||
|
auto write_line(std::string message) -> void;
|
||||||
|
|
||||||
|
/// Build and send well-formed IRC message from individual parameters
|
||||||
|
auto write_irc(std::string) -> void;
|
||||||
|
auto write_irc(std::string, std::string_view) -> void;
|
||||||
|
template <typename... Args>
|
||||||
|
auto write_irc(std::string front, std::string_view next, Args ...rest) -> void;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Connection(boost::asio::io_context & io);
|
Connection(boost::asio::io_context & io);
|
||||||
|
|
||||||
boost::signals2::signal<void()> sig_connect;
|
boost::signals2::signal<void()> sig_connect;
|
||||||
boost::signals2::signal<void()> sig_disconnect;
|
boost::signals2::signal<void()> sig_disconnect;
|
||||||
boost::signals2::signal<void(IrcCommand, const IrcMsg &)> sig_ircmsg;
|
boost::signals2::signal<void(IrcCommand, const IrcMsg &)> sig_ircmsg;
|
||||||
|
boost::signals2::signal<void(SnoteTag, SnoteMatch &)> sig_snote;
|
||||||
|
|
||||||
auto get_executor() -> boost::asio::any_io_executor {
|
auto get_executor() -> boost::asio::any_io_executor {
|
||||||
return stream_.get_executor();
|
return stream_.get_executor();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write bytes into the socket. Messages should be properly newline terminated.
|
|
||||||
auto write_line(std::string message) -> void;
|
|
||||||
|
|
||||||
auto connect(
|
auto connect(
|
||||||
boost::asio::io_context & io,
|
boost::asio::io_context & io,
|
||||||
std::string host,
|
std::string host,
|
||||||
@ -42,5 +50,36 @@ public:
|
|||||||
) -> boost::asio::awaitable<void>;
|
) -> boost::asio::awaitable<void>;
|
||||||
|
|
||||||
auto close() -> void;
|
auto close() -> void;
|
||||||
|
|
||||||
|
auto send_ping(std::string_view) -> void;
|
||||||
|
auto send_pong(std::string_view) -> void;
|
||||||
|
auto send_pass(std::string_view) -> void;
|
||||||
|
auto send_user(std::string_view, std::string_view) -> void;
|
||||||
|
auto send_nick(std::string_view) -> void;
|
||||||
|
auto send_cap_ls() -> void;
|
||||||
|
auto send_cap_end() -> void;
|
||||||
|
auto send_cap_req(std::string_view) -> void;
|
||||||
|
auto send_privmsg(std::string_view, std::string_view) -> void;
|
||||||
|
auto send_notice(std::string_view, std::string_view) -> void;
|
||||||
|
auto send_authenticate(std::string_view message) -> void;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename... Args>
|
||||||
|
auto Connection::write_irc(std::string front, std::string_view next, Args ...rest) -> void
|
||||||
|
{
|
||||||
|
auto const is_invalid = [](char const x) -> bool
|
||||||
|
{
|
||||||
|
return x == '\0' || x == '\r' || x == '\n' || x == ' ';
|
||||||
|
};
|
||||||
|
|
||||||
|
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(std::move(front), rest...);
|
||||||
|
}
|
||||||
|
18
main.cpp
18
main.cpp
@ -1,7 +1,6 @@
|
|||||||
#include "connection.hpp"
|
#include "connection.hpp"
|
||||||
#include "ircmsg.hpp"
|
#include "ircmsg.hpp"
|
||||||
#include "settings.hpp"
|
#include "settings.hpp"
|
||||||
#include "write_irc.hpp"
|
|
||||||
|
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
|
|
||||||
@ -11,42 +10,27 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "ping_thread.hpp"
|
|
||||||
#include "registration_thread.hpp"
|
#include "registration_thread.hpp"
|
||||||
#include "self_thread.hpp"
|
#include "self_thread.hpp"
|
||||||
#include "snote_thread.hpp"
|
|
||||||
|
|
||||||
#include "irc_coroutine.hpp"
|
#include "irc_coroutine.hpp"
|
||||||
|
|
||||||
using namespace std::chrono_literals;
|
using namespace std::chrono_literals;
|
||||||
|
|
||||||
irc_coroutine example(Connection& connection) {
|
|
||||||
auto [cmd1, msg1] = co_await wait_command{IrcCommand::RPL_WELCOME};
|
|
||||||
std::cout << "WELCOME " << msg1.args[0] << "\n";
|
|
||||||
auto [cmd5, msg5] = co_await wait_command{IrcCommand::RPL_ISUPPORT};
|
|
||||||
std::cout << "ISUPPORT " << msg5.args[0] << "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
auto start(boost::asio::io_context & io, Settings const& settings) -> void
|
auto start(boost::asio::io_context & io, Settings const& settings) -> void
|
||||||
{
|
{
|
||||||
auto const connection = std::make_shared<Connection>(io);
|
auto const connection = std::make_shared<Connection>(io);
|
||||||
|
|
||||||
RegistrationThread::start(*connection, settings.password, settings.username, settings.realname, settings.nickname);
|
RegistrationThread::start(*connection, settings.password, settings.username, settings.realname, settings.nickname);
|
||||||
PingThread::start(*connection);
|
|
||||||
SelfThread::start(*connection);
|
SelfThread::start(*connection);
|
||||||
auto const snote_thread = SnoteThread::start(*connection);
|
|
||||||
|
|
||||||
/*
|
connection->sig_snote.connect([](auto tag, auto &match) {
|
||||||
snote_thread->sig_snote.connect([](auto tag, auto &match) {
|
|
||||||
std::cout << "SNOTE " << static_cast<int>(tag) << std::endl;
|
std::cout << "SNOTE " << static_cast<int>(tag) << std::endl;
|
||||||
for (auto c : match.get_results())
|
for (auto c : match.get_results())
|
||||||
{
|
{
|
||||||
std::cout << " " << std::string_view{c.first, c.second} << std::endl;
|
std::cout << " " << std::string_view{c.first, c.second} << std::endl;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
*/
|
|
||||||
auto logic = example(*connection);
|
|
||||||
logic.start(*connection);
|
|
||||||
|
|
||||||
boost::asio::co_spawn(
|
boost::asio::co_spawn(
|
||||||
io,
|
io,
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
#include "connection.hpp"
|
#include "connection.hpp"
|
||||||
#include "ircmsg.hpp"
|
#include "ircmsg.hpp"
|
||||||
#include "write_irc.hpp"
|
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
@ -25,10 +24,10 @@ RegistrationThread::RegistrationThread(
|
|||||||
|
|
||||||
auto RegistrationThread::on_connect() -> void
|
auto RegistrationThread::on_connect() -> void
|
||||||
{
|
{
|
||||||
send_cap_ls(connection_);
|
connection_.send_cap_ls();
|
||||||
send_pass(connection_, password_);
|
connection_.send_pass(password_);
|
||||||
send_user(connection_, username_, realname_);
|
connection_.send_user(username_, realname_);
|
||||||
send_nick(connection_, nickname_);
|
connection_.send_nick(nickname_);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto RegistrationThread::send_req() -> void
|
auto RegistrationThread::send_req() -> void
|
||||||
@ -63,13 +62,13 @@ auto RegistrationThread::send_req() -> void
|
|||||||
if (not outstanding.empty())
|
if (not outstanding.empty())
|
||||||
{
|
{
|
||||||
request.pop_back();
|
request.pop_back();
|
||||||
send_cap_req(connection_, request);
|
connection_.send_cap_req(request);
|
||||||
|
|
||||||
listen_for_cap_ack();
|
listen_for_cap_ack();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
send_cap_end(connection_);
|
connection_.send_cap_end();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,7 +85,7 @@ auto RegistrationThread::on_msg_cap_ack(IrcMsg const& msg) -> void
|
|||||||
if (outstanding.empty())
|
if (outstanding.empty())
|
||||||
{
|
{
|
||||||
message_handle_.disconnect();
|
message_handle_.disconnect();
|
||||||
send_cap_end(connection_);
|
connection_.send_cap_end();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
#include "snote_thread.hpp"
|
#include "snote.hpp"
|
||||||
|
|
||||||
#include "connection.hpp"
|
|
||||||
#include "c_callback.hpp"
|
#include "c_callback.hpp"
|
||||||
|
|
||||||
#include <hs.h>
|
#include <hs.h>
|
||||||
@ -9,6 +8,7 @@
|
|||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <optional>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
@ -114,64 +114,60 @@ static auto setup_database() -> hs_database_t*
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
auto SnoteThread::start(Connection& connection) -> std::shared_ptr<SnoteThread>
|
SnoteCore::SnoteCore() noexcept
|
||||||
{
|
{
|
||||||
auto thread = std::make_shared<SnoteThread>();
|
db_.reset(setup_database());
|
||||||
|
|
||||||
thread->db_.reset(setup_database());
|
|
||||||
|
|
||||||
hs_scratch_t* scratch = nullptr;
|
hs_scratch_t* scratch = nullptr;
|
||||||
if (HS_SUCCESS != hs_alloc_scratch(thread->db_.get(), &scratch))
|
if (HS_SUCCESS != hs_alloc_scratch(db_.get(), &scratch))
|
||||||
{
|
{
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
thread->scratch_.reset(scratch);
|
scratch_.reset(scratch);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto SnoteCore::match(const IrcMsg &msg) -> std::optional<std::pair<SnoteTag, SnoteMatch>>
|
||||||
|
{
|
||||||
static char const* const prefix = "*** Notice -- ";
|
static char const* const prefix = "*** Notice -- ";
|
||||||
connection.sig_ircmsg.connect([&connection, thread](auto cmd, auto& msg)
|
|
||||||
|
auto& args = msg.args;
|
||||||
|
if ("*" != args[0] || !args[1].starts_with(prefix)) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto const message = args[1].substr(strlen(prefix));
|
||||||
|
|
||||||
|
unsigned match_id;
|
||||||
|
auto cb = [&match_id](unsigned id, unsigned long long, unsigned long long, unsigned) -> int
|
||||||
{
|
{
|
||||||
auto& args = msg.args;
|
match_id = id;
|
||||||
if (IrcCommand::NOTICE == cmd && "*" == args[0] && args[1].starts_with(prefix))
|
return 1; // stop scanning
|
||||||
{
|
};
|
||||||
auto const message = args[1].substr(strlen(prefix));
|
|
||||||
|
|
||||||
unsigned match_id;
|
auto const scan_result =
|
||||||
auto cb = [&match_id](unsigned id, unsigned long long, unsigned long long, unsigned) -> int
|
hs_scan(
|
||||||
{
|
db_.get(),
|
||||||
match_id = id;
|
message.data(), message.size(),
|
||||||
return 1; // stop scanning
|
0, // no flags
|
||||||
};
|
scratch_.get(),
|
||||||
|
CCallback<decltype(cb)>::invoke, &cb
|
||||||
|
);
|
||||||
|
|
||||||
auto const scan_result =
|
switch (scan_result)
|
||||||
hs_scan(
|
{
|
||||||
thread->db_.get(),
|
case HS_SUCCESS:
|
||||||
message.data(), message.size(),
|
BOOST_LOG_TRIVIAL(warning) << "Unknown snote: " << message;
|
||||||
0, // no flags
|
return std::nullopt;
|
||||||
thread->scratch_.get(),
|
|
||||||
CCallback<decltype(cb)>::invoke, &cb
|
|
||||||
);
|
|
||||||
|
|
||||||
switch (scan_result)
|
case HS_SCAN_TERMINATED:
|
||||||
{
|
{
|
||||||
case HS_SUCCESS:
|
auto& pattern = patterns[match_id];
|
||||||
BOOST_LOG_TRIVIAL(warning) << "Unknown snote: " << message;
|
return std::make_pair(pattern.tag, SnoteMatch{pattern.regex, message});
|
||||||
break;
|
}
|
||||||
|
|
||||||
case HS_SCAN_TERMINATED:
|
default:
|
||||||
{
|
abort();
|
||||||
auto& pattern = patterns[match_id];
|
}
|
||||||
auto match = SnoteMatch{pattern.regex, message};
|
|
||||||
thread->sig_snote(pattern.tag, match);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return thread;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SnoteMatch::get_results() -> std::match_results<std::string_view::const_iterator> const&
|
auto SnoteMatch::get_results() -> std::match_results<std::string_view::const_iterator> const&
|
||||||
@ -191,7 +187,7 @@ auto SnoteMatch::get_results() -> std::match_results<std::string_view::const_ite
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SnoteThread::DbDeleter::operator()(hs_database_t * db) const -> void
|
auto SnoteCore::DbDeleter::operator()(hs_database_t * db) const -> void
|
||||||
{
|
{
|
||||||
if (HS_SUCCESS != hs_free_database(db))
|
if (HS_SUCCESS != hs_free_database(db))
|
||||||
{
|
{
|
||||||
@ -199,10 +195,12 @@ auto SnoteThread::DbDeleter::operator()(hs_database_t * db) const -> void
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SnoteThread::ScratchDeleter::operator()(hs_scratch_t * scratch) const -> void
|
auto SnoteCore::ScratchDeleter::operator()(hs_scratch_t * scratch) const -> void
|
||||||
{
|
{
|
||||||
if (HS_SUCCESS != hs_free_scratch(scratch))
|
if (HS_SUCCESS != hs_free_scratch(scratch))
|
||||||
{
|
{
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SnoteCore snoteCore;
|
@ -1,11 +1,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <boost/signals2.hpp>
|
#include "ircmsg.hpp"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
|
#include <tuple>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
class Connection;
|
class Connection;
|
||||||
struct hs_database;
|
struct hs_database;
|
||||||
@ -44,7 +46,7 @@ private:
|
|||||||
std::variant<std::pair<std::regex const&, std::string_view>, std::match_results<std::string_view::const_iterator>> components_;
|
std::variant<std::pair<std::regex const&, std::string_view>, std::match_results<std::string_view::const_iterator>> components_;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SnoteThread
|
struct SnoteCore
|
||||||
{
|
{
|
||||||
struct DbDeleter
|
struct DbDeleter
|
||||||
{
|
{
|
||||||
@ -62,7 +64,8 @@ struct SnoteThread
|
|||||||
/// @brief HyperScan scratch space
|
/// @brief HyperScan scratch space
|
||||||
std::unique_ptr<hs_scratch, ScratchDeleter> scratch_;
|
std::unique_ptr<hs_scratch, ScratchDeleter> scratch_;
|
||||||
|
|
||||||
boost::signals2::signal<void(SnoteTag, SnoteMatch&)> sig_snote;
|
SnoteCore() noexcept;
|
||||||
|
auto match(const IrcMsg &msg) -> std::optional<std::pair<SnoteTag, SnoteMatch>>;
|
||||||
static auto start(Connection& connection) -> std::shared_ptr<SnoteThread>;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern SnoteCore snoteCore;
|
@ -1,7 +1,6 @@
|
|||||||
#include "watchdog_thread.hpp"
|
#include "watchdog_thread.hpp"
|
||||||
|
|
||||||
#include "connection.hpp"
|
#include "connection.hpp"
|
||||||
#include "write_irc.hpp"
|
|
||||||
|
|
||||||
#include <boost/asio/steady_timer.hpp>
|
#include <boost/asio/steady_timer.hpp>
|
||||||
|
|
||||||
@ -43,7 +42,7 @@ auto WatchdogThread::on_timeout() -> void
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
send_ping(connection_, "watchdog");
|
connection_.send_ping("watchdog");
|
||||||
stalled_ = true;
|
stalled_ = true;
|
||||||
timer_.expires_after(WatchdogThread::TIMEOUT);
|
timer_.expires_after(WatchdogThread::TIMEOUT);
|
||||||
start_timer();
|
start_timer();
|
||||||
|
107
write_irc.cpp
107
write_irc.cpp
@ -1,107 +0,0 @@
|
|||||||
#include "write_irc.hpp"
|
|
||||||
|
|
||||||
#include "connection.hpp"
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
auto write_irc(Connection& connection, std::string message) -> void
|
|
||||||
{
|
|
||||||
connection.write_line(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
|
|
||||||
{
|
|
||||||
if (last.end() != std::find_if(last.begin(), last.end(), is_invalid_last))
|
|
||||||
{
|
|
||||||
throw std::runtime_error{"bad irc argument"};
|
|
||||||
}
|
|
||||||
|
|
||||||
front += " :";
|
|
||||||
front += last;
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto send_privmsg(Connection& connection, std::string_view target, std::string_view message) -> void
|
|
||||||
{
|
|
||||||
write_irc(connection, "PRIVMSG", target, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto send_notice(Connection& connection, std::string_view target, std::string_view message) -> void
|
|
||||||
{
|
|
||||||
write_irc(connection, "NOTICE", target, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto send_authenticate(Connection& connection, std::string_view message) -> void
|
|
||||||
{
|
|
||||||
write_irc(connection, "AUTHENTICATE", message);
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string_view>
|
|
||||||
|
|
||||||
class Connection;
|
|
||||||
|
|
||||||
auto send_ping(Connection&, std::string_view) -> void;
|
|
||||||
auto send_pong(Connection&, std::string_view) -> void;
|
|
||||||
auto send_pass(Connection&, std::string_view) -> void;
|
|
||||||
auto send_user(Connection&, std::string_view, std::string_view) -> void;
|
|
||||||
auto send_nick(Connection&, std::string_view) -> void;
|
|
||||||
auto send_cap_ls(Connection&) -> void;
|
|
||||||
auto send_cap_end(Connection&) -> void;
|
|
||||||
auto send_cap_req(Connection&, std::string_view) -> void;
|
|
||||||
auto send_privmsg(Connection&, std::string_view, std::string_view) -> void;
|
|
||||||
auto send_notice(Connection&, std::string_view, std::string_view) -> void;
|
|
||||||
auto send_authenticate(Connection& connection, std::string_view message) -> void;
|
|
Loading…
x
Reference in New Issue
Block a user