mass reformat
This commit is contained in:
parent
fd4612d385
commit
093515c3ec
232
.clang-format
Normal file
232
.clang-format
Normal file
@ -0,0 +1,232 @@
|
||||
---
|
||||
Language: Cpp
|
||||
# BasedOnStyle: WebKit
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: BlockIndent
|
||||
AlignArrayOfStructures: None
|
||||
AlignConsecutiveAssignments:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: true
|
||||
AlignConsecutiveBitFields:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: false
|
||||
AlignConsecutiveDeclarations:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: false
|
||||
AlignConsecutiveMacros:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: false
|
||||
AlignConsecutiveShortCaseStatements:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCaseColons: false
|
||||
AlignEscapedNewlines: Right
|
||||
AlignOperands: DontAlign
|
||||
AlignTrailingComments:
|
||||
Kind: Never
|
||||
OverEmptyLines: 0
|
||||
AllowAllArgumentsOnNextLine: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowBreakBeforeNoexceptSpecifier: Never
|
||||
AllowShortBlocksOnASingleLine: Empty
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortCompoundRequirementOnASingleLine: true
|
||||
AllowShortEnumsOnASingleLine: true
|
||||
AllowShortFunctionsOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: MultiLine
|
||||
AttributeMacros:
|
||||
- __capability
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BitFieldColonSpacing: Both
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: false
|
||||
AfterClass: true
|
||||
AfterControlStatement: Always
|
||||
AfterEnum: true
|
||||
AfterExternBlock: false
|
||||
AfterFunction: true
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: true
|
||||
AfterUnion: true
|
||||
BeforeCatch: true
|
||||
BeforeElse: true
|
||||
BeforeLambdaBody: false
|
||||
BeforeWhile: true
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: true
|
||||
SplitEmptyRecord: true
|
||||
SplitEmptyNamespace: true
|
||||
BreakAdjacentStringLiterals: true
|
||||
BreakAfterAttributes: Leave
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakArrays: true
|
||||
BreakBeforeBinaryOperators: All
|
||||
BreakBeforeConceptDeclarations: Always
|
||||
BreakBeforeBraces: Custom
|
||||
BreakBeforeInlineASMColon: OnlyMultiline
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializers: BeforeComma
|
||||
BreakInheritanceList: BeforeColon
|
||||
BreakStringLiterals: true
|
||||
ColumnLimit: 0
|
||||
CommentPragmas: "^ IWYU pragma:"
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
EmptyLineAfterAccessModifier: Never
|
||||
EmptyLineBeforeAccessModifier: LogicalBlock
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
FixNamespaceComments: false
|
||||
ForEachMacros: []
|
||||
IfMacros: []
|
||||
IncludeBlocks: Preserve
|
||||
IncludeCategories:
|
||||
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
|
||||
Priority: 2
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
|
||||
Priority: 3
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
- Regex: ".*"
|
||||
Priority: 1
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
IncludeIsMainRegex: "(Test)?$"
|
||||
IncludeIsMainSourceRegex: ""
|
||||
IndentAccessModifiers: false
|
||||
IndentCaseBlocks: false
|
||||
IndentCaseLabels: false
|
||||
IndentExternBlock: AfterExternBlock
|
||||
IndentGotoLabels: true
|
||||
IndentPPDirectives: None
|
||||
IndentRequiresClause: true
|
||||
IndentWidth: 4
|
||||
IndentWrappedFunctionNames: false
|
||||
InsertBraces: false
|
||||
InsertNewlineAtEOF: false
|
||||
InsertTrailingCommas: None
|
||||
IntegerLiteralSeparator:
|
||||
Binary: 0
|
||||
BinaryMinDigits: 0
|
||||
Decimal: 0
|
||||
DecimalMinDigits: 0
|
||||
Hex: 0
|
||||
HexMinDigits: 0
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||
KeepEmptyLinesAtEOF: false
|
||||
LambdaBodyIndentation: Signature
|
||||
LineEnding: LF
|
||||
MacroBlockBegin: ""
|
||||
MacroBlockEnd: ""
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: Inner
|
||||
ObjCBinPackProtocolList: Auto
|
||||
ObjCBlockIndentWidth: 4
|
||||
ObjCBreakBeforeNestedBlockParam: true
|
||||
ObjCSpaceAfterProperty: true
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PackConstructorInitializers: BinPack
|
||||
PenaltyBreakAssignment: 2
|
||||
PenaltyBreakBeforeFirstCallParameter: 19
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakOpenParenthesis: 0
|
||||
PenaltyBreakScopeResolution: 500
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyBreakTemplateDeclaration: 10
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyIndentedWhitespace: 0
|
||||
PenaltyReturnTypeOnItsOwnLine: 60
|
||||
PointerAlignment: Right
|
||||
PPIndentWidth: -1
|
||||
QualifierAlignment: Left
|
||||
ReferenceAlignment: Pointer
|
||||
ReflowComments: true
|
||||
RemoveBracesLLVM: false
|
||||
RemoveParentheses: Leave
|
||||
RemoveSemicolon: false
|
||||
RequiresClausePosition: OwnLine
|
||||
RequiresExpressionIndentation: OuterScope
|
||||
SeparateDefinitionBlocks: Leave
|
||||
ShortNamespaceLines: 1
|
||||
SkipMacroDefinitionBody: false
|
||||
SortIncludes: CaseSensitive
|
||||
SortJavaStaticImport: Before
|
||||
SortUsingDeclarations: LexicographicNumeric
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceAroundPointerQualifiers: Default
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCaseColon: false
|
||||
SpaceBeforeCpp11BracedList: false
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeJsonColon: false
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceBeforeParensOptions:
|
||||
AfterControlStatements: true
|
||||
AfterForeachMacros: true
|
||||
AfterFunctionDefinitionName: false
|
||||
AfterFunctionDeclarationName: false
|
||||
AfterIfMacros: true
|
||||
AfterOverloadedOperator: false
|
||||
AfterPlacementOperator: true
|
||||
AfterRequiresInClause: false
|
||||
AfterRequiresInExpression: false
|
||||
BeforeNonEmptyParentheses: false
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceBeforeSquareBrackets: false
|
||||
SpaceInEmptyBlock: true
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: Never
|
||||
SpacesInContainerLiterals: true
|
||||
SpacesInLineCommentPrefix:
|
||||
Minimum: 1
|
||||
Maximum: -1
|
||||
SpacesInParens: Never
|
||||
SpacesInParensOptions:
|
||||
InCStyleCasts: false
|
||||
InConditionalStatements: false
|
||||
InEmptyParentheses: false
|
||||
Other: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: Latest
|
||||
StatementAttributeLikeMacros: []
|
||||
StatementMacros: []
|
||||
TabWidth: 8
|
||||
UseTab: Never
|
||||
VerilogBreakBetweenInstancePorts: true
|
||||
WhitespaceSensitiveMacros: []
|
@ -12,11 +12,11 @@ namespace {
|
||||
|
||||
using namespace std::literals;
|
||||
|
||||
Connection::Connection(boost::asio::io_context & io)
|
||||
: stream_{io}
|
||||
, watchdog_timer_{io}
|
||||
, write_posted_{false}
|
||||
, stalled_{false}
|
||||
Connection::Connection(boost::asio::io_context &io)
|
||||
: stream_{io}
|
||||
, watchdog_timer_{io}
|
||||
, write_posted_{false}
|
||||
, stalled_{false}
|
||||
{
|
||||
}
|
||||
|
||||
@ -24,28 +24,32 @@ auto Connection::write_buffers() -> void
|
||||
{
|
||||
std::vector<boost::asio::const_buffer> buffers;
|
||||
buffers.reserve(write_strings_.size());
|
||||
for (auto const& elt : write_strings_)
|
||||
for (const auto &elt : write_strings_)
|
||||
{
|
||||
buffers.push_back(boost::asio::buffer(elt));
|
||||
}
|
||||
boost::asio::async_write(
|
||||
stream_,
|
||||
buffers,
|
||||
[this, strings = std::move(write_strings_)](boost::system::error_code const& error, std::size_t)
|
||||
{
|
||||
if (not error) {
|
||||
if (write_strings_.empty()) {
|
||||
[this, strings = std::move(write_strings_)](const boost::system::error_code &error, std::size_t) {
|
||||
if (not error)
|
||||
{
|
||||
if (write_strings_.empty())
|
||||
{
|
||||
write_posted_ = false;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
write_buffers();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
write_strings_.clear();
|
||||
}
|
||||
|
||||
auto Connection::connect(
|
||||
boost::asio::io_context & io,
|
||||
boost::asio::io_context &io,
|
||||
std::string host,
|
||||
std::string port
|
||||
) -> boost::asio::awaitable<void>
|
||||
@ -53,29 +57,28 @@ auto Connection::connect(
|
||||
using namespace std::placeholders;
|
||||
|
||||
// keep connection alive while coroutine is active
|
||||
auto const self = shared_from_this();
|
||||
const auto self = shared_from_this();
|
||||
|
||||
{
|
||||
auto resolver = boost::asio::ip::tcp::resolver{io};
|
||||
auto const endpoints = co_await resolver.async_resolve(host, port, boost::asio::use_awaitable);
|
||||
auto const endpoint = co_await boost::asio::async_connect(stream_, endpoints, boost::asio::use_awaitable);
|
||||
BOOST_LOG_TRIVIAL(debug) << "CONNECTED: " << endpoint;
|
||||
const auto endpoints = co_await resolver.async_resolve(host, port, boost::asio::use_awaitable);
|
||||
const auto endpoint = co_await boost::asio::async_connect(stream_, endpoints, boost::asio::use_awaitable);
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug) << "CONNECTED: " << endpoint;
|
||||
sig_connect();
|
||||
}
|
||||
|
||||
// Start the queue writer after connection
|
||||
watchdog();
|
||||
|
||||
for(LineBuffer buffer{32'768};;)
|
||||
for (LineBuffer buffer{32'768};;)
|
||||
{
|
||||
boost::system::error_code error;
|
||||
auto const n = co_await stream_.async_read_some(buffer.get_buffer(), boost::asio::redirect_error(boost::asio::use_awaitable, error));
|
||||
const auto n = co_await stream_.async_read_some(buffer.get_buffer(), boost::asio::redirect_error(boost::asio::use_awaitable, error));
|
||||
if (error)
|
||||
{
|
||||
break;
|
||||
}
|
||||
buffer.add_bytes(n, [this](char * line) {
|
||||
buffer.add_bytes(n, [this](char *line) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "RECV: " << line;
|
||||
watchdog_activity();
|
||||
dispatch_line(line);
|
||||
@ -84,14 +87,15 @@ auto Connection::connect(
|
||||
|
||||
watchdog_timer_.cancel();
|
||||
stream_.close();
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug) << "DISCONNECTED";
|
||||
sig_disconnect();
|
||||
}
|
||||
|
||||
auto Connection::watchdog() -> void
|
||||
{
|
||||
watchdog_timer_.expires_after(watchdog_duration);
|
||||
watchdog_timer_.async_wait([this](auto const& error)
|
||||
{
|
||||
watchdog_timer_.async_wait([this](const auto &error) {
|
||||
if (not error)
|
||||
{
|
||||
if (stalled_)
|
||||
@ -118,15 +122,17 @@ auto Connection::watchdog_activity() -> void
|
||||
/// Parse IRC message line and dispatch it to the ircmsg slot.
|
||||
auto Connection::dispatch_line(char *line) -> void
|
||||
{
|
||||
auto const msg = parse_irc_message(line);
|
||||
auto const recognized = IrcCommandHash::in_word_set(msg.command.data(), msg.command.size());
|
||||
auto const command
|
||||
const auto msg = parse_irc_message(line);
|
||||
const auto recognized = IrcCommandHash::in_word_set(msg.command.data(), msg.command.size());
|
||||
const auto command
|
||||
= recognized
|
||||
&& recognized->min_args <= msg.args.size()
|
||||
&& recognized->max_args >= msg.args.size()
|
||||
? recognized->command : IrcCommand::UNKNOWN;
|
||||
&& recognized->min_args <= msg.args.size()
|
||||
&& recognized->max_args >= msg.args.size()
|
||||
? recognized->command
|
||||
: IrcCommand::UNKNOWN;
|
||||
|
||||
switch (command) {
|
||||
switch (command)
|
||||
{
|
||||
|
||||
// Respond to pings immediate and discard
|
||||
case IrcCommand::PING:
|
||||
@ -145,7 +151,8 @@ auto Connection::dispatch_line(char *line) -> void
|
||||
|
||||
// Server notice generate snote events but not IRC command events
|
||||
case IrcCommand::NOTICE:
|
||||
if (auto match = snoteCore.match(msg)) {
|
||||
if (auto match = snoteCore.match(msg))
|
||||
{
|
||||
sig_snote(*match);
|
||||
break;
|
||||
}
|
||||
@ -156,7 +163,6 @@ auto Connection::dispatch_line(char *line) -> void
|
||||
sig_ircmsg(command, msg);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
auto Connection::write_line(std::string message) -> void
|
||||
@ -165,9 +171,10 @@ auto Connection::write_line(std::string message) -> void
|
||||
message += "\r\n";
|
||||
write_strings_.push_back(std::move(message));
|
||||
|
||||
if (not write_posted_) {
|
||||
if (not write_posted_)
|
||||
{
|
||||
write_posted_ = true;
|
||||
boost::asio::post(stream_.get_executor(), [weak = weak_from_this()](){
|
||||
boost::asio::post(stream_.get_executor(), [weak = weak_from_this()]() {
|
||||
if (auto self = weak.lock())
|
||||
{
|
||||
self->write_buffers();
|
||||
@ -181,8 +188,7 @@ auto Connection::close() -> void
|
||||
stream_.close();
|
||||
}
|
||||
|
||||
static
|
||||
auto is_invalid_last(char x) -> bool
|
||||
static auto is_invalid_last(char x) -> bool
|
||||
{
|
||||
return x == '\0' || x == '\r' || x == '\n';
|
||||
}
|
||||
@ -261,7 +267,8 @@ auto Connection::send_authenticate(std::string_view message) -> void
|
||||
|
||||
auto Connection::on_authenticate(const std::string_view chunk) -> void
|
||||
{
|
||||
if (chunk != "+"sv) {
|
||||
if (chunk != "+"sv)
|
||||
{
|
||||
authenticate_buffer_ += chunk;
|
||||
}
|
||||
|
||||
@ -275,7 +282,9 @@ auto Connection::on_authenticate(const std::string_view chunk) -> void
|
||||
{
|
||||
decoded.resize(len);
|
||||
sig_authenticate(decoded);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(debug) << "Invalid AUTHENTICATE base64"sv;
|
||||
send_authenticate("*"sv); // abort SASL
|
||||
}
|
||||
@ -300,9 +309,10 @@ auto Connection::send_authenticate_encoded(std::string_view body) -> void
|
||||
std::string encoded(mybase64::encoded_size(body.size()), 0);
|
||||
mybase64::encode(body, encoded.data());
|
||||
|
||||
for (size_t lo = 0; lo < encoded.size(); lo += 400) {
|
||||
for (size_t lo = 0; lo < encoded.size(); lo += 400)
|
||||
{
|
||||
const auto hi = std::min(lo + 400, encoded.size());
|
||||
const std::string_view chunk { encoded.begin() + lo, encoded.begin() + hi };
|
||||
const std::string_view chunk{encoded.begin() + lo, encoded.begin() + hi};
|
||||
send_authenticate(chunk);
|
||||
}
|
||||
|
||||
@ -310,4 +320,4 @@ auto Connection::send_authenticate_encoded(std::string_view body) -> void
|
||||
{
|
||||
send_authenticate("+"sv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "ircmsg.hpp"
|
||||
#include "irc_command.hpp"
|
||||
#include "ircmsg.hpp"
|
||||
#include "snote.hpp"
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
@ -27,7 +27,7 @@ private:
|
||||
std::string authenticate_buffer_;
|
||||
|
||||
auto write_buffers() -> void;
|
||||
auto dispatch_line(char * line) -> void;
|
||||
auto dispatch_line(char *line) -> void;
|
||||
|
||||
static constexpr std::chrono::seconds watchdog_duration = std::chrono::seconds{30};
|
||||
auto watchdog() -> void;
|
||||
@ -40,10 +40,10 @@ private:
|
||||
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;
|
||||
auto write_irc(std::string front, std::string_view next, Args... rest) -> void;
|
||||
|
||||
public:
|
||||
Connection(boost::asio::io_context & io);
|
||||
Connection(boost::asio::io_context &io);
|
||||
|
||||
boost::signals2::signal<void()> sig_connect;
|
||||
boost::signals2::signal<void()> sig_disconnect;
|
||||
@ -51,12 +51,13 @@ public:
|
||||
boost::signals2::signal<void(SnoteMatch &)> sig_snote;
|
||||
boost::signals2::signal<void(std::string_view)> sig_authenticate;
|
||||
|
||||
auto get_executor() -> boost::asio::any_io_executor {
|
||||
auto get_executor() -> boost::asio::any_io_executor
|
||||
{
|
||||
return stream_.get_executor();
|
||||
}
|
||||
|
||||
auto connect(
|
||||
boost::asio::io_context & io,
|
||||
boost::asio::io_context &io,
|
||||
std::string host,
|
||||
std::string port
|
||||
) -> boost::asio::awaitable<void>;
|
||||
@ -81,16 +82,15 @@ public:
|
||||
};
|
||||
|
||||
template <typename... Args>
|
||||
auto Connection::write_irc(std::string front, std::string_view next, Args ...rest) -> void
|
||||
auto Connection::write_irc(std::string front, std::string_view next, Args... rest) -> void
|
||||
{
|
||||
auto const is_invalid = [](char const x) -> bool
|
||||
{
|
||||
const auto is_invalid = [](const char 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))
|
||||
|| next.front() == ':'
|
||||
|| next.end() != std::find_if(next.begin(), next.end(), is_invalid))
|
||||
{
|
||||
throw std::runtime_error{"bad irc argument"};
|
||||
}
|
||||
|
@ -1,21 +1,20 @@
|
||||
#include "irc_coroutine.hpp"
|
||||
|
||||
auto irc_coroutine::is_running() -> bool {
|
||||
auto irc_coroutine::is_running() -> bool
|
||||
{
|
||||
return promise().connection_ != nullptr;
|
||||
}
|
||||
auto irc_coroutine::exception() -> std::exception_ptr {
|
||||
auto irc_coroutine::exception() -> std::exception_ptr
|
||||
{
|
||||
return promise().exception_;
|
||||
}
|
||||
|
||||
auto irc_coroutine::start(Connection& connection) -> void {
|
||||
auto irc_coroutine::start(Connection &connection) -> void
|
||||
{
|
||||
promise().connection_ = connection.shared_from_this();
|
||||
resume();
|
||||
}
|
||||
|
||||
void wait_ircmsg::stop() {
|
||||
ircmsg_slot_.disconnect();
|
||||
}
|
||||
void wait_ircmsg::stop() { ircmsg_slot_.disconnect(); }
|
||||
|
||||
void wait_timeout::stop() {
|
||||
timer_.reset();
|
||||
}
|
||||
void wait_timeout::stop() { timer_.reset(); }
|
||||
|
@ -11,7 +11,8 @@
|
||||
struct irc_promise;
|
||||
|
||||
/// A coroutine that can co_await on various IRC events
|
||||
struct irc_coroutine : std::coroutine_handle<irc_promise> {
|
||||
struct irc_coroutine : std::coroutine_handle<irc_promise>
|
||||
{
|
||||
using promise_type = irc_promise;
|
||||
|
||||
/// Start the coroutine and associate it with a specific connection.
|
||||
@ -44,22 +45,25 @@ struct irc_promise
|
||||
auto final_suspend() noexcept -> std::suspend_always { return {}; }
|
||||
|
||||
// Normal termination
|
||||
auto return_void() -> void {
|
||||
auto return_void() -> void
|
||||
{
|
||||
connection_.reset();
|
||||
}
|
||||
|
||||
// Abnormal termination - remember the exception
|
||||
auto unhandled_exception() -> void {
|
||||
auto unhandled_exception() -> void
|
||||
{
|
||||
connection_.reset();
|
||||
exception_ = std::current_exception();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename ... Ts>
|
||||
template <typename... Ts>
|
||||
class Wait;
|
||||
|
||||
/// Argument to a Wait that expects one or more IRC messages
|
||||
class wait_ircmsg {
|
||||
class wait_ircmsg
|
||||
{
|
||||
// Vector of commands this wait is expecting. Leave empty to accept all messages.
|
||||
std::vector<IrcCommand> want_cmds_;
|
||||
|
||||
@ -69,26 +73,38 @@ class wait_ircmsg {
|
||||
public:
|
||||
using result_type = std::pair<IrcCommand, const IrcMsg &>;
|
||||
|
||||
wait_ircmsg(std::initializer_list<IrcCommand> want_cmds) : want_cmds_{want_cmds} {}
|
||||
wait_ircmsg(std::initializer_list<IrcCommand> want_cmds)
|
||||
: want_cmds_{want_cmds}
|
||||
{
|
||||
}
|
||||
|
||||
template <size_t I, typename... Ts> auto start(Wait<Ts...>& command) -> void;
|
||||
template <size_t I, typename... Ts>
|
||||
auto start(Wait<Ts...> &command) -> void;
|
||||
auto stop() -> void;
|
||||
};
|
||||
|
||||
class wait_timeout {
|
||||
class wait_timeout
|
||||
{
|
||||
std::optional<boost::asio::steady_timer> timer_;
|
||||
std::chrono::milliseconds timeout_;
|
||||
|
||||
public:
|
||||
struct result_type {};
|
||||
wait_timeout(std::chrono::milliseconds timeout) : timeout_{timeout} {}
|
||||
struct result_type
|
||||
{
|
||||
};
|
||||
wait_timeout(std::chrono::milliseconds timeout)
|
||||
: timeout_{timeout}
|
||||
{
|
||||
}
|
||||
|
||||
template <size_t I, typename... Ts> auto start(Wait<Ts...>& command) -> void;
|
||||
template <size_t I, typename... Ts>
|
||||
auto start(Wait<Ts...> &command) -> void;
|
||||
auto stop() -> void;
|
||||
};
|
||||
|
||||
template<typename ... Ts>
|
||||
class Wait {
|
||||
template <typename... Ts>
|
||||
class Wait
|
||||
{
|
||||
|
||||
// State associated with each wait mode
|
||||
std::tuple<Ts...> modes_;
|
||||
@ -105,31 +121,39 @@ class Wait {
|
||||
boost::signals2::scoped_connection disconnect_slot_;
|
||||
|
||||
template <size_t I>
|
||||
auto start_mode() -> void {
|
||||
auto start_mode() -> void
|
||||
{
|
||||
std::get<I>(modes_).template start<I, Ts...>(*this);
|
||||
}
|
||||
|
||||
template <std::size_t... Indices>
|
||||
auto start_modes(std::index_sequence<Indices...>) -> void {
|
||||
auto start_modes(std::index_sequence<Indices...>) -> void
|
||||
{
|
||||
(start_mode<Indices>(), ...);
|
||||
}
|
||||
|
||||
template <std::size_t... Indices>
|
||||
auto stop_modes(std::index_sequence<Indices...>) -> void {
|
||||
auto stop_modes(std::index_sequence<Indices...>) -> void
|
||||
{
|
||||
(std::get<Indices>(modes_).stop(), ...);
|
||||
}
|
||||
|
||||
public:
|
||||
Wait(Ts &&...modes) : modes_{std::forward<Ts>(modes)...} {}
|
||||
Wait(Ts &&...modes)
|
||||
: modes_{std::forward<Ts>(modes)...}
|
||||
{
|
||||
}
|
||||
|
||||
// Get the connection that this coroutine was started with.
|
||||
auto get_connection() const -> Connection & {
|
||||
auto get_connection() const -> Connection &
|
||||
{
|
||||
return *handle_.promise().connection_;
|
||||
}
|
||||
|
||||
// Store a successful result and resume the coroutine
|
||||
template <size_t I, typename... Args>
|
||||
auto complete(Args &&...args) -> void {
|
||||
auto complete(Args &&...args) -> void
|
||||
{
|
||||
result_.emplace(std::in_place_index<I>, std::forward<Args>(args)...);
|
||||
handle_.resume();
|
||||
}
|
||||
@ -148,23 +172,22 @@ template <size_t I, typename... Ts>
|
||||
auto wait_ircmsg::start(Wait<Ts...> &command) -> void
|
||||
{
|
||||
ircmsg_slot_ = command.get_connection().sig_ircmsg.connect([this, &command](auto cmd, auto &msg) {
|
||||
auto const wanted =
|
||||
want_cmds_.empty() ||
|
||||
std::find(want_cmds_.begin(), want_cmds_.end(), cmd) != want_cmds_.end();
|
||||
if (wanted) {
|
||||
const auto wanted = want_cmds_.empty() || std::find(want_cmds_.begin(), want_cmds_.end(), cmd) != want_cmds_.end();
|
||||
if (wanted)
|
||||
{
|
||||
command.template complete<I>(cmd, msg);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
template <size_t I, typename... Ts>
|
||||
auto wait_timeout::start(Wait<Ts...>& command) -> void
|
||||
auto wait_timeout::start(Wait<Ts...> &command) -> void
|
||||
{
|
||||
timer_.emplace(command.get_connection().get_executor());
|
||||
timer_->expires_after(timeout_);
|
||||
timer_->async_wait([this, &command](auto const& error)
|
||||
{
|
||||
if (not error) {
|
||||
timer_->async_wait([this, &command](const auto &error) {
|
||||
if (not error)
|
||||
{
|
||||
timer_.reset();
|
||||
command.template complete<I>();
|
||||
}
|
||||
@ -176,7 +199,7 @@ auto Wait<Ts...>::await_suspend(std::coroutine_handle<irc_promise> handle) -> vo
|
||||
{
|
||||
handle_ = handle;
|
||||
|
||||
auto const tuple_size = std::tuple_size_v<decltype(modes_)>;
|
||||
const auto tuple_size = std::tuple_size_v<decltype(modes_)>;
|
||||
start_modes(std::make_index_sequence<tuple_size>{});
|
||||
|
||||
disconnect_slot_ = get_connection().sig_disconnect.connect([this]() {
|
||||
@ -187,14 +210,17 @@ auto Wait<Ts...>::await_suspend(std::coroutine_handle<irc_promise> handle) -> vo
|
||||
template <typename... Ts>
|
||||
auto Wait<Ts...>::await_resume() -> std::variant<typename Ts::result_type...>
|
||||
{
|
||||
auto const tuple_size = std::tuple_size_v<decltype(modes_)>;
|
||||
const auto tuple_size = std::tuple_size_v<decltype(modes_)>;
|
||||
stop_modes(std::make_index_sequence<tuple_size>{});
|
||||
|
||||
disconnect_slot_.disconnect();
|
||||
|
||||
if (result_) {
|
||||
if (result_)
|
||||
{
|
||||
return std::move(*result_);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error{"connection terminated"};
|
||||
}
|
||||
}
|
||||
|
137
ircmsg.cpp
137
ircmsg.cpp
@ -4,56 +4,68 @@
|
||||
#include "ircmsg.hpp"
|
||||
|
||||
namespace {
|
||||
class Parser {
|
||||
char* msg_;
|
||||
class Parser
|
||||
{
|
||||
char *msg_;
|
||||
inline static char empty[1];
|
||||
|
||||
inline void trim() {
|
||||
while (*msg_ == ' ') msg_++;
|
||||
inline void trim()
|
||||
{
|
||||
while (*msg_ == ' ')
|
||||
msg_++;
|
||||
}
|
||||
|
||||
public:
|
||||
Parser(char* msg) : msg_(msg) {
|
||||
if (msg_ == nullptr) {
|
||||
Parser(char *msg)
|
||||
: msg_(msg)
|
||||
{
|
||||
if (msg_ == nullptr)
|
||||
{
|
||||
msg_ = empty;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
trim();
|
||||
}
|
||||
}
|
||||
|
||||
char* word() {
|
||||
auto const start = msg_;
|
||||
while (*msg_ != '\0' && *msg_ != ' ') msg_++;
|
||||
if (*msg_ != '\0') { // prepare for next token
|
||||
char *word()
|
||||
{
|
||||
const auto start = msg_;
|
||||
while (*msg_ != '\0' && *msg_ != ' ')
|
||||
msg_++;
|
||||
if (*msg_ != '\0')
|
||||
{ // prepare for next token
|
||||
*msg_++ = '\0';
|
||||
trim();
|
||||
}
|
||||
return start;
|
||||
}
|
||||
|
||||
bool match(char c) {
|
||||
if (c == *msg_) {
|
||||
bool match(char c)
|
||||
{
|
||||
if (c == *msg_)
|
||||
{
|
||||
msg_++;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isempty() const {
|
||||
return *msg_ == '\0';
|
||||
}
|
||||
bool isempty() const { return *msg_ == '\0'; }
|
||||
|
||||
char const* peek() {
|
||||
return msg_;
|
||||
}
|
||||
const char *peek() { return msg_; }
|
||||
};
|
||||
|
||||
std::string_view unescape_tag_value(char* const val)
|
||||
std::string_view unescape_tag_value(char *const val)
|
||||
{
|
||||
// only start copying at the first escape character
|
||||
// skip everything before that
|
||||
auto cursor = strchr(val, '\\');
|
||||
if (cursor == nullptr) { return {val}; }
|
||||
if (cursor == nullptr)
|
||||
{
|
||||
return {val};
|
||||
}
|
||||
|
||||
auto write = cursor;
|
||||
for (; *cursor; cursor++)
|
||||
@ -63,12 +75,23 @@ std::string_view unescape_tag_value(char* const val)
|
||||
cursor++;
|
||||
switch (*cursor)
|
||||
{
|
||||
default : *write++ = *cursor; break;
|
||||
case ':' : *write++ = ';' ; break;
|
||||
case 's' : *write++ = ' ' ; break;
|
||||
case 'r' : *write++ = '\r' ; break;
|
||||
case 'n' : *write++ = '\n' ; break;
|
||||
case '\0': return {val, write};
|
||||
default:
|
||||
*write++ = *cursor;
|
||||
break;
|
||||
case ':':
|
||||
*write++ = ';';
|
||||
break;
|
||||
case 's':
|
||||
*write++ = ' ';
|
||||
break;
|
||||
case 'r':
|
||||
*write++ = '\r';
|
||||
break;
|
||||
case 'n':
|
||||
*write++ = '\n';
|
||||
break;
|
||||
case '\0':
|
||||
return {val, write};
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -81,50 +104,61 @@ std::string_view unescape_tag_value(char* const val)
|
||||
|
||||
} // namespace
|
||||
|
||||
auto parse_irc_tags(char* str) -> std::vector<irctag>
|
||||
auto parse_irc_tags(char *str) -> std::vector<irctag>
|
||||
{
|
||||
std::vector<irctag> tags;
|
||||
|
||||
do {
|
||||
do
|
||||
{
|
||||
auto val = strsep(&str, ";");
|
||||
auto key = strsep(&val, "=");
|
||||
if ('\0' == *key) {
|
||||
if ('\0' == *key)
|
||||
{
|
||||
throw irc_parse_error(irc_error_code::MISSING_TAG);
|
||||
}
|
||||
if (nullptr == val) {
|
||||
if (nullptr == val)
|
||||
{
|
||||
tags.emplace_back(key, "");
|
||||
} else {
|
||||
tags.emplace_back(std::string_view{key, val-1}, unescape_tag_value(val));
|
||||
}
|
||||
} while(nullptr != str);
|
||||
else
|
||||
{
|
||||
tags.emplace_back(std::string_view{key, val - 1}, unescape_tag_value(val));
|
||||
}
|
||||
}
|
||||
while (nullptr != str);
|
||||
|
||||
return tags;
|
||||
}
|
||||
|
||||
auto parse_irc_message(char* msg) -> IrcMsg
|
||||
auto parse_irc_message(char *msg) -> IrcMsg
|
||||
{
|
||||
Parser p {msg};
|
||||
Parser p{msg};
|
||||
IrcMsg out;
|
||||
|
||||
/* MESSAGE TAGS */
|
||||
if (p.match('@')) {
|
||||
if (p.match('@'))
|
||||
{
|
||||
out.tags = parse_irc_tags(p.word());
|
||||
}
|
||||
|
||||
/* MESSAGE SOURCE */
|
||||
if (p.match(':')) {
|
||||
if (p.match(':'))
|
||||
{
|
||||
out.source = p.word();
|
||||
}
|
||||
|
||||
/* MESSAGE COMMANDS */
|
||||
out.command = p.word();
|
||||
if (out.command.empty()) {
|
||||
if (out.command.empty())
|
||||
{
|
||||
throw irc_parse_error{irc_error_code::MISSING_COMMAND};
|
||||
}
|
||||
|
||||
/* MESSAGE ARGUMENTS */
|
||||
while (!p.isempty()) {
|
||||
if (p.match(':')) {
|
||||
while (!p.isempty())
|
||||
{
|
||||
if (p.match(':'))
|
||||
{
|
||||
out.args.push_back(p.peek());
|
||||
break;
|
||||
}
|
||||
@ -134,16 +168,19 @@ auto parse_irc_message(char* msg) -> IrcMsg
|
||||
return out;
|
||||
}
|
||||
|
||||
auto IrcMsg::hassource() const -> bool
|
||||
{
|
||||
return source.data() != nullptr;
|
||||
}
|
||||
auto IrcMsg::hassource() const -> bool { return source.data() != nullptr; }
|
||||
|
||||
auto operator<<(std::ostream& out, irc_error_code code) -> std::ostream&
|
||||
auto operator<<(std::ostream &out, irc_error_code code) -> std::ostream &
|
||||
{
|
||||
switch(code) {
|
||||
case irc_error_code::MISSING_COMMAND: out << "MISSING COMMAND"; return out;
|
||||
case irc_error_code::MISSING_TAG: out << "MISSING TAG"; return out;
|
||||
default: return out;
|
||||
switch (code)
|
||||
{
|
||||
case irc_error_code::MISSING_COMMAND:
|
||||
out << "MISSING COMMAND";
|
||||
return out;
|
||||
case irc_error_code::MISSING_TAG:
|
||||
out << "MISSING TAG";
|
||||
return out;
|
||||
default:
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
44
ircmsg.hpp
44
ircmsg.hpp
@ -9,9 +9,13 @@ struct irctag
|
||||
std::string_view key;
|
||||
std::string_view val;
|
||||
|
||||
irctag(std::string_view key, std::string_view val) : key{key}, val{val} {}
|
||||
irctag(std::string_view key, std::string_view val)
|
||||
: key{key}
|
||||
, val{val}
|
||||
{
|
||||
}
|
||||
|
||||
friend auto operator==(irctag const&, irctag const&) -> bool = default;
|
||||
friend auto operator==(const irctag &, const irctag &) -> bool = default;
|
||||
};
|
||||
|
||||
struct IrcMsg
|
||||
@ -24,30 +28,38 @@ struct IrcMsg
|
||||
IrcMsg() = default;
|
||||
|
||||
IrcMsg(
|
||||
std::vector<irctag> && tags,
|
||||
std::vector<irctag> &&tags,
|
||||
std::string_view source,
|
||||
std::string_view command,
|
||||
std::vector<std::string_view> && args)
|
||||
: tags(std::move(tags)),
|
||||
args(std::move(args)),
|
||||
source{source},
|
||||
command{command} {}
|
||||
std::vector<std::string_view> &&args
|
||||
)
|
||||
: tags(std::move(tags))
|
||||
, args(std::move(args))
|
||||
, source{source}
|
||||
, command{command}
|
||||
{
|
||||
}
|
||||
|
||||
bool hassource() const;
|
||||
bool hassource() const;
|
||||
|
||||
friend bool operator==(IrcMsg const&, IrcMsg const&) = default;
|
||||
friend bool operator==(const IrcMsg &, const IrcMsg &) = default;
|
||||
};
|
||||
|
||||
enum class irc_error_code {
|
||||
enum class irc_error_code
|
||||
{
|
||||
MISSING_TAG,
|
||||
MISSING_COMMAND,
|
||||
};
|
||||
|
||||
auto operator<<(std::ostream& out, irc_error_code) -> std::ostream&;
|
||||
auto operator<<(std::ostream &out, irc_error_code) -> std::ostream &;
|
||||
|
||||
struct irc_parse_error : public std::exception {
|
||||
struct irc_parse_error : public std::exception
|
||||
{
|
||||
irc_error_code code;
|
||||
irc_parse_error(irc_error_code code) : code(code) {}
|
||||
irc_parse_error(irc_error_code code)
|
||||
: code(code)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@ -57,6 +69,6 @@ struct irc_parse_error : public std::exception {
|
||||
*
|
||||
* Returns zero for success, non-zero for parse error.
|
||||
*/
|
||||
auto parse_irc_message(char* msg) -> IrcMsg;
|
||||
auto parse_irc_message(char *msg) -> IrcMsg;
|
||||
|
||||
auto parse_irc_tags(char* msg) -> std::vector<irctag>;
|
||||
auto parse_irc_tags(char *msg) -> std::vector<irctag>;
|
||||
|
@ -34,7 +34,11 @@ public:
|
||||
*
|
||||
* @param n Buffer size
|
||||
*/
|
||||
LineBuffer(std::size_t n) : buffer(n), end_{buffer.begin()} {}
|
||||
LineBuffer(std::size_t n)
|
||||
: buffer(n)
|
||||
, end_{buffer.begin()}
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the available buffer space
|
||||
@ -60,7 +64,7 @@ public:
|
||||
*/
|
||||
auto add_bytes(std::size_t n, std::invocable<char *> auto line_cb) -> void
|
||||
{
|
||||
auto const start = end_;
|
||||
const auto start = end_;
|
||||
std::advance(end_, n);
|
||||
|
||||
// new data is now located in [start, end_)
|
||||
|
25
main.cpp
25
main.cpp
@ -13,11 +13,11 @@
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
auto start(boost::asio::io_context & io, Settings const& settings) -> void
|
||||
auto start(boost::asio::io_context &io, const Settings &settings) -> void
|
||||
{
|
||||
auto const connection = std::make_shared<Connection>(io);
|
||||
const auto connection = std::make_shared<Connection>(io);
|
||||
|
||||
auto const selfThread = SelfThread::start(*connection);
|
||||
const auto selfThread = SelfThread::start(*connection);
|
||||
RegistrationThread::start(*connection, settings, selfThread);
|
||||
|
||||
connection->sig_snote.connect([](auto &match) {
|
||||
@ -29,22 +29,21 @@ auto start(boost::asio::io_context & io, Settings const& settings) -> void
|
||||
});
|
||||
|
||||
boost::asio::co_spawn(
|
||||
io,
|
||||
connection->connect(io, settings.host, settings.service),
|
||||
[&io, &settings](std::exception_ptr e)
|
||||
{
|
||||
io, connection->connect(io, settings.host, settings.service),
|
||||
[&io, &settings](std::exception_ptr e) {
|
||||
auto timer = std::make_shared<boost::asio::steady_timer>(io);
|
||||
|
||||
timer->expires_after(5s);
|
||||
timer->async_wait([&io, &settings, timer](auto) {
|
||||
start(io, settings);
|
||||
});
|
||||
});
|
||||
timer->async_wait(
|
||||
[&io, &settings, timer](auto) { start(io, settings); }
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
auto get_settings() -> Settings
|
||||
{
|
||||
if (auto config_stream = std::ifstream {"config.toml"})
|
||||
if (auto config_stream = std::ifstream{"config.toml"})
|
||||
{
|
||||
return Settings::from_stream(config_stream);
|
||||
}
|
||||
@ -57,7 +56,7 @@ auto get_settings() -> Settings
|
||||
|
||||
auto main() -> int
|
||||
{
|
||||
auto const settings = get_settings();
|
||||
const auto settings = get_settings();
|
||||
auto io = boost::asio::io_context{};
|
||||
start(io, settings);
|
||||
io.run();
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include <unordered_set>
|
||||
|
||||
RegistrationThread::RegistrationThread(
|
||||
Connection& connection,
|
||||
Connection &connection,
|
||||
const Settings &settings,
|
||||
std::shared_ptr<SelfThread> self
|
||||
)
|
||||
@ -22,7 +22,10 @@ RegistrationThread::RegistrationThread(
|
||||
auto RegistrationThread::on_connect() -> void
|
||||
{
|
||||
connection_.send_cap_ls();
|
||||
connection_.send_pass(settings_.password);
|
||||
if (not settings_.password.empty())
|
||||
{
|
||||
connection_.send_pass(settings_.password);
|
||||
}
|
||||
connection_.send_user(settings_.username, settings_.realname);
|
||||
connection_.send_nick(settings_.nickname);
|
||||
}
|
||||
@ -30,7 +33,7 @@ auto RegistrationThread::on_connect() -> void
|
||||
auto RegistrationThread::send_req() -> void
|
||||
{
|
||||
std::string request;
|
||||
std::vector<char const*> want {
|
||||
std::vector<const char *> want{
|
||||
"account-notify",
|
||||
"account-tag",
|
||||
"batch",
|
||||
@ -46,11 +49,12 @@ auto RegistrationThread::send_req() -> void
|
||||
"solanum.chat/realhost",
|
||||
};
|
||||
|
||||
if (settings_.sasl_mechanism == "PLAIN") {
|
||||
if (not settings_.sasl_mechanism.empty())
|
||||
{
|
||||
want.push_back("sasl");
|
||||
}
|
||||
|
||||
for (auto const cap : want)
|
||||
for (const auto cap : want)
|
||||
{
|
||||
if (caps.contains(cap))
|
||||
{
|
||||
@ -73,7 +77,7 @@ auto RegistrationThread::send_req() -> void
|
||||
}
|
||||
}
|
||||
|
||||
auto RegistrationThread::on_msg_cap_ack(IrcMsg const& msg) -> void
|
||||
auto RegistrationThread::on_msg_cap_ack(const IrcMsg &msg) -> void
|
||||
{
|
||||
auto in = std::istringstream{std::string{msg.args[2]}};
|
||||
std::for_each(
|
||||
@ -86,27 +90,32 @@ auto RegistrationThread::on_msg_cap_ack(IrcMsg const& msg) -> void
|
||||
if (outstanding.empty())
|
||||
{
|
||||
message_handle_.disconnect();
|
||||
|
||||
if (settings_.sasl_mechanism.empty()) {
|
||||
|
||||
if (settings_.sasl_mechanism.empty())
|
||||
{
|
||||
connection_.send_cap_end();
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
self_->start_sasl(std::make_unique<SaslPlain>(settings_.sasl_authcid, settings_.sasl_authzid, settings_.sasl_password));
|
||||
connection_.sig_ircmsg.connect_extended([thread = shared_from_this()](auto &slot, auto cmd, auto &msg) {
|
||||
switch (cmd) {
|
||||
default: break;
|
||||
case IrcCommand::RPL_SASLSUCCESS:
|
||||
case IrcCommand::ERR_SASLFAIL:
|
||||
thread->connection_.send_cap_end();
|
||||
slot.disconnect();
|
||||
switch (cmd)
|
||||
{
|
||||
default:
|
||||
break;
|
||||
case IrcCommand::RPL_SASLSUCCESS:
|
||||
case IrcCommand::ERR_SASLFAIL:
|
||||
thread->connection_.send_cap_end();
|
||||
slot.disconnect();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto RegistrationThread::on_msg_cap_ls(IrcMsg const& msg) -> void
|
||||
auto RegistrationThread::on_msg_cap_ls(const IrcMsg &msg) -> void
|
||||
{
|
||||
std::string_view const* kvs;
|
||||
const std::string_view *kvs;
|
||||
bool last;
|
||||
|
||||
if (3 == msg.args.size())
|
||||
@ -130,14 +139,14 @@ auto RegistrationThread::on_msg_cap_ls(IrcMsg const& msg) -> void
|
||||
std::istream_iterator<std::string>{in},
|
||||
std::istream_iterator<std::string>{},
|
||||
[this](std::string x) {
|
||||
auto const eq = x.find('=');
|
||||
const auto eq = x.find('=');
|
||||
if (eq == x.npos)
|
||||
{
|
||||
caps.emplace(x, std::string{});
|
||||
}
|
||||
else
|
||||
{
|
||||
caps.emplace(std::string{x, 0, eq}, std::string{x, eq+1, x.npos});
|
||||
caps.emplace(std::string{x, 0, eq}, std::string{x, eq + 1, x.npos});
|
||||
}
|
||||
}
|
||||
);
|
||||
@ -150,17 +159,16 @@ auto RegistrationThread::on_msg_cap_ls(IrcMsg const& msg) -> void
|
||||
}
|
||||
|
||||
auto RegistrationThread::start(
|
||||
Connection& connection,
|
||||
Connection &connection,
|
||||
const Settings &settings,
|
||||
std::shared_ptr<SelfThread> self
|
||||
) -> std::shared_ptr<RegistrationThread>
|
||||
{
|
||||
auto const thread = std::make_shared<RegistrationThread>(connection, std::move(settings), std::move(self));
|
||||
const auto thread = std::make_shared<RegistrationThread>(connection, std::move(settings), std::move(self));
|
||||
|
||||
thread->listen_for_cap_ls();
|
||||
|
||||
thread->connect_handle_ = connection.sig_connect.connect([thread]()
|
||||
{
|
||||
thread->connect_handle_ = connection.sig_connect.connect([thread]() {
|
||||
thread->connect_handle_.disconnect();
|
||||
thread->on_connect();
|
||||
});
|
||||
@ -170,8 +178,7 @@ auto RegistrationThread::start(
|
||||
|
||||
auto RegistrationThread::listen_for_cap_ack() -> void
|
||||
{
|
||||
message_handle_ = connection_.sig_ircmsg.connect([thread = shared_from_this()](IrcCommand cmd, IrcMsg const& msg)
|
||||
{
|
||||
message_handle_ = connection_.sig_ircmsg.connect([thread = shared_from_this()](IrcCommand cmd, const IrcMsg &msg) {
|
||||
if (IrcCommand::CAP == cmd && msg.args.size() >= 2 && "ACK" == msg.args[1])
|
||||
{
|
||||
thread->on_msg_cap_ack(msg);
|
||||
@ -181,11 +188,15 @@ auto RegistrationThread::listen_for_cap_ack() -> void
|
||||
|
||||
auto RegistrationThread::listen_for_cap_ls() -> void
|
||||
{
|
||||
message_handle_ = connection_.sig_ircmsg.connect([thread = shared_from_this()](IrcCommand cmd, IrcMsg const& msg)
|
||||
{
|
||||
message_handle_ = connection_.sig_ircmsg.connect([thread = shared_from_this()](IrcCommand cmd, const IrcMsg &msg) {
|
||||
if (IrcCommand::CAP == cmd && msg.args.size() >= 2 && "LS" == msg.args[1])
|
||||
{
|
||||
thread->on_msg_cap_ls(msg);
|
||||
}
|
||||
else if (IrcCommand::RPL_WELCOME == cmd)
|
||||
{
|
||||
// Server doesn't support CAP negotiation
|
||||
thread->message_handle_.disconnect();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "connection.hpp"
|
||||
#include "settings.hpp"
|
||||
#include "self_thread.hpp"
|
||||
#include "settings.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
@ -11,7 +11,7 @@
|
||||
|
||||
class RegistrationThread : public std::enable_shared_from_this<RegistrationThread>
|
||||
{
|
||||
Connection& connection_;
|
||||
Connection &connection_;
|
||||
const Settings &settings_;
|
||||
std::shared_ptr<SelfThread> self_;
|
||||
|
||||
@ -23,21 +23,21 @@ class RegistrationThread : public std::enable_shared_from_this<RegistrationThrea
|
||||
|
||||
auto on_connect() -> void;
|
||||
auto send_req() -> void;
|
||||
auto on_msg_cap_ls(IrcMsg const& msg) -> void;
|
||||
auto on_msg_cap_ack(IrcMsg const& msg) -> void;
|
||||
auto on_msg_cap_ls(const IrcMsg &msg) -> void;
|
||||
auto on_msg_cap_ack(const IrcMsg &msg) -> void;
|
||||
|
||||
auto listen_for_cap_ack() -> void;
|
||||
auto listen_for_cap_ls() -> void;
|
||||
|
||||
public:
|
||||
RegistrationThread(
|
||||
Connection& connection_,
|
||||
Connection &connection_,
|
||||
const Settings &,
|
||||
std::shared_ptr<SelfThread> self
|
||||
);
|
||||
|
||||
static auto start(
|
||||
Connection& connection,
|
||||
Connection &connection,
|
||||
const Settings &,
|
||||
std::shared_ptr<SelfThread> self
|
||||
) -> std::shared_ptr<RegistrationThread>;
|
||||
|
@ -7,10 +7,6 @@
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#include "event.hpp"
|
||||
|
||||
struct Connection;
|
||||
|
||||
class SaslMechanism
|
||||
{
|
||||
public:
|
||||
|
@ -9,12 +9,12 @@
|
||||
|
||||
using namespace std::literals;
|
||||
|
||||
auto SelfThread::on_welcome(IrcMsg const& irc) -> void
|
||||
auto SelfThread::on_welcome(const IrcMsg &irc) -> void
|
||||
{
|
||||
nickname_ = irc.args[0];
|
||||
}
|
||||
|
||||
auto SelfThread::on_nick(IrcMsg const& irc) -> void
|
||||
auto SelfThread::on_nick(const IrcMsg &irc) -> void
|
||||
{
|
||||
if (is_my_mask(irc.source))
|
||||
{
|
||||
@ -22,12 +22,12 @@ auto SelfThread::on_nick(IrcMsg const& irc) -> void
|
||||
}
|
||||
}
|
||||
|
||||
auto SelfThread::on_umodeis(IrcMsg const& irc) -> void
|
||||
auto SelfThread::on_umodeis(const IrcMsg &irc) -> void
|
||||
{
|
||||
mode_ = irc.args[1];
|
||||
}
|
||||
|
||||
auto SelfThread::on_join(IrcMsg const& irc) -> void
|
||||
auto SelfThread::on_join(const IrcMsg &irc) -> void
|
||||
{
|
||||
if (is_my_mask(irc.source))
|
||||
{
|
||||
@ -35,7 +35,7 @@ auto SelfThread::on_join(IrcMsg const& irc) -> void
|
||||
}
|
||||
}
|
||||
|
||||
auto SelfThread::on_kick(IrcMsg const& irc) -> void
|
||||
auto SelfThread::on_kick(const IrcMsg &irc) -> void
|
||||
{
|
||||
if (is_my_nick(irc.args[1]))
|
||||
{
|
||||
@ -43,7 +43,7 @@ auto SelfThread::on_kick(IrcMsg const& irc) -> void
|
||||
}
|
||||
}
|
||||
|
||||
auto SelfThread::on_part(IrcMsg const& irc) -> void
|
||||
auto SelfThread::on_part(const IrcMsg &irc) -> void
|
||||
{
|
||||
if (is_my_mask(irc.source))
|
||||
{
|
||||
@ -51,12 +51,12 @@ auto SelfThread::on_part(IrcMsg const& irc) -> void
|
||||
}
|
||||
}
|
||||
|
||||
auto SelfThread::on_mode(IrcMsg const& irc) -> void
|
||||
auto SelfThread::on_mode(const IrcMsg &irc) -> void
|
||||
{
|
||||
if (is_my_nick(irc.args[0]))
|
||||
{
|
||||
auto polarity = true;
|
||||
for (char const c : irc.args[1])
|
||||
for (const char c : irc.args[1])
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
@ -73,7 +73,7 @@ auto SelfThread::on_mode(IrcMsg const& irc) -> void
|
||||
}
|
||||
else
|
||||
{
|
||||
auto const ix = mode_.find(c);
|
||||
const auto ix = mode_.find(c);
|
||||
if (ix != std::string::npos)
|
||||
{
|
||||
mode_.erase(ix, 1);
|
||||
@ -87,42 +87,64 @@ auto SelfThread::on_mode(IrcMsg const& irc) -> void
|
||||
|
||||
auto SelfThread::on_isupport(const IrcMsg &msg) -> void
|
||||
{
|
||||
auto const hi = msg.args.size() - 1;
|
||||
const auto hi = msg.args.size() - 1;
|
||||
for (int i = 1; i < hi; ++i)
|
||||
{
|
||||
auto &entry = msg.args[i];
|
||||
|
||||
// Leading minus means to stop support
|
||||
if (entry.starts_with("-")) {
|
||||
auto const key = std::string{entry.substr(1)};
|
||||
if (auto cursor = isupport_.find(key); cursor != isupport_.end()) {
|
||||
if (entry.starts_with("-"))
|
||||
{
|
||||
const auto key = std::string{entry.substr(1)};
|
||||
if (auto cursor = isupport_.find(key); cursor != isupport_.end())
|
||||
{
|
||||
isupport_.erase(cursor);
|
||||
}
|
||||
} else if (auto const cursor = entry.find('='); cursor != entry.npos) {
|
||||
isupport_.emplace(entry.substr(0, cursor), entry.substr(cursor+1));
|
||||
} else {
|
||||
}
|
||||
else if (const auto cursor = entry.find('='); cursor != entry.npos)
|
||||
{
|
||||
isupport_.emplace(entry.substr(0, cursor), entry.substr(cursor + 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
isupport_.emplace(entry, std::string{});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto SelfThread::start(Connection& connection) -> std::shared_ptr<SelfThread>
|
||||
auto SelfThread::start(Connection &connection) -> std::shared_ptr<SelfThread>
|
||||
{
|
||||
auto thread = std::make_shared<SelfThread>(connection);
|
||||
|
||||
connection.sig_ircmsg.connect([thread](auto cmd, auto& msg)
|
||||
{
|
||||
connection.sig_ircmsg.connect([thread](auto cmd, auto &msg) {
|
||||
switch (cmd)
|
||||
{
|
||||
case IrcCommand::JOIN: thread->on_join(msg); break;
|
||||
case IrcCommand::KICK: thread->on_kick(msg); break;
|
||||
case IrcCommand::MODE: thread->on_mode(msg); break;
|
||||
case IrcCommand::NICK: thread->on_nick(msg); break;
|
||||
case IrcCommand::PART: thread->on_part(msg); break;
|
||||
case IrcCommand::RPL_ISUPPORT: thread->on_isupport(msg); break;
|
||||
case IrcCommand::RPL_UMODEIS: thread->on_umodeis(msg); break;
|
||||
case IrcCommand::RPL_WELCOME: thread->on_welcome(msg); break;
|
||||
default: break;
|
||||
case IrcCommand::JOIN:
|
||||
thread->on_join(msg);
|
||||
break;
|
||||
case IrcCommand::KICK:
|
||||
thread->on_kick(msg);
|
||||
break;
|
||||
case IrcCommand::MODE:
|
||||
thread->on_mode(msg);
|
||||
break;
|
||||
case IrcCommand::NICK:
|
||||
thread->on_nick(msg);
|
||||
break;
|
||||
case IrcCommand::PART:
|
||||
thread->on_part(msg);
|
||||
break;
|
||||
case IrcCommand::RPL_ISUPPORT:
|
||||
thread->on_isupport(msg);
|
||||
break;
|
||||
case IrcCommand::RPL_UMODEIS:
|
||||
thread->on_umodeis(msg);
|
||||
break;
|
||||
case IrcCommand::RPL_WELCOME:
|
||||
thread->on_welcome(msg);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
@ -133,17 +155,17 @@ auto SelfThread::start(Connection& connection) -> std::shared_ptr<SelfThread>
|
||||
return thread;
|
||||
}
|
||||
|
||||
auto SelfThread::get_my_nickname() const -> std::string const&
|
||||
auto SelfThread::get_my_nickname() const -> const std::string &
|
||||
{
|
||||
return nickname_;
|
||||
}
|
||||
|
||||
auto SelfThread::get_my_mode() const -> std::string const&
|
||||
auto SelfThread::get_my_mode() const -> const std::string &
|
||||
{
|
||||
return mode_;
|
||||
}
|
||||
|
||||
auto SelfThread::get_my_channels() const -> std::unordered_set<std::string> const&
|
||||
auto SelfThread::get_my_channels() const -> const std::unordered_set<std::string> &
|
||||
{
|
||||
return channels_;
|
||||
}
|
||||
@ -155,7 +177,7 @@ auto SelfThread::is_my_nick(std::string_view nick) const -> bool
|
||||
|
||||
auto SelfThread::is_my_mask(std::string_view mask) const -> bool
|
||||
{
|
||||
auto const bang = mask.find('!');
|
||||
const auto bang = mask.find('!');
|
||||
return bang != std::string_view::npos && nickname_ == mask.substr(0, bang);
|
||||
}
|
||||
|
||||
@ -168,7 +190,8 @@ auto SelfThread::on_authenticate(const std::string_view body) -> void
|
||||
return;
|
||||
}
|
||||
|
||||
if (auto reply = sasl_mechanism_->step(body)) {
|
||||
if (auto reply = sasl_mechanism_->step(body))
|
||||
{
|
||||
|
||||
connection_.send_authenticate_encoded(*reply);
|
||||
|
||||
@ -182,7 +205,8 @@ auto SelfThread::on_authenticate(const std::string_view body) -> void
|
||||
|
||||
auto SelfThread::start_sasl(std::unique_ptr<SaslMechanism> mechanism) -> void
|
||||
{
|
||||
if (sasl_mechanism_) {
|
||||
if (sasl_mechanism_)
|
||||
{
|
||||
connection_.send_authenticate("*"sv); // abort SASL
|
||||
}
|
||||
|
||||
|
@ -11,11 +11,11 @@ struct IrcMsg;
|
||||
|
||||
/**
|
||||
* @brief Thread to track this connection's identity, and IRC state.
|
||||
*
|
||||
*
|
||||
*/
|
||||
class SelfThread
|
||||
{
|
||||
Connection& connection_;
|
||||
Connection &connection_;
|
||||
|
||||
std::string nickname_;
|
||||
std::string mode_;
|
||||
@ -26,27 +26,29 @@ class SelfThread
|
||||
|
||||
std::unique_ptr<SaslMechanism> sasl_mechanism_;
|
||||
|
||||
auto on_welcome(IrcMsg const& irc) -> void;
|
||||
auto on_isupport(IrcMsg const& irc) -> void;
|
||||
auto on_nick(IrcMsg const& irc) -> void;
|
||||
auto on_umodeis(IrcMsg const& irc) -> void;
|
||||
auto on_join(IrcMsg const& irc) -> void;
|
||||
auto on_kick(IrcMsg const& irc) -> void;
|
||||
auto on_part(IrcMsg const& irc) -> void;
|
||||
auto on_mode(IrcMsg const& irc) -> void;
|
||||
auto on_welcome(const IrcMsg &irc) -> void;
|
||||
auto on_isupport(const IrcMsg &irc) -> void;
|
||||
auto on_nick(const IrcMsg &irc) -> void;
|
||||
auto on_umodeis(const IrcMsg &irc) -> void;
|
||||
auto on_join(const IrcMsg &irc) -> void;
|
||||
auto on_kick(const IrcMsg &irc) -> void;
|
||||
auto on_part(const IrcMsg &irc) -> void;
|
||||
auto on_mode(const IrcMsg &irc) -> void;
|
||||
auto on_authenticate(std::string_view) -> void;
|
||||
|
||||
public:
|
||||
SelfThread(Connection& connection) : connection_{connection} {}
|
||||
static auto start(Connection&) -> std::shared_ptr<SelfThread>;
|
||||
SelfThread(Connection &connection)
|
||||
: connection_{connection}
|
||||
{
|
||||
}
|
||||
static auto start(Connection &) -> std::shared_ptr<SelfThread>;
|
||||
|
||||
auto start_sasl(std::unique_ptr<SaslMechanism> mechanism) -> void;
|
||||
|
||||
auto get_my_nickname() const -> std::string const&;
|
||||
auto get_my_mode() const -> std::string const&;
|
||||
auto get_my_channels() const -> std::unordered_set<std::string> const&;
|
||||
auto get_my_nickname() const -> const std::string &;
|
||||
auto get_my_mode() const -> const std::string &;
|
||||
auto get_my_channels() const -> const std::unordered_set<std::string> &;
|
||||
|
||||
auto is_my_nick(std::string_view nick) const -> bool;
|
||||
auto is_my_mask(std::string_view nick) const -> bool;
|
||||
|
||||
};
|
||||
|
@ -3,12 +3,12 @@
|
||||
#define TOML_ENABLE_FORMATTERS 0
|
||||
#include <toml++/toml.hpp>
|
||||
|
||||
auto Settings::from_stream(std::istream & in) -> Settings
|
||||
auto Settings::from_stream(std::istream &in) -> Settings
|
||||
{
|
||||
auto const config = toml::parse(in);
|
||||
const auto config = toml::parse(in);
|
||||
return Settings{
|
||||
.host = config["host"].value_or(std::string{}),
|
||||
.service = config["service"].value_or(std::string{}),
|
||||
.host = config["host"].value_or(std::string{}),
|
||||
.service = config["service"].value_or(std::string{}),
|
||||
.password = config["password"].value_or(std::string{}),
|
||||
.username = config["username"].value_or(std::string{}),
|
||||
.realname = config["realname"].value_or(std::string{}),
|
||||
|
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <istream>
|
||||
#include <string>
|
||||
|
||||
struct Settings
|
||||
{
|
||||
@ -17,6 +17,5 @@ struct Settings
|
||||
std::string sasl_authzid;
|
||||
std::string sasl_password;
|
||||
|
||||
static auto from_stream(std::istream & in) -> Settings;
|
||||
static auto from_stream(std::istream &in) -> Settings;
|
||||
};
|
||||
|
||||
|
85
snote.cpp
85
snote.cpp
@ -17,20 +17,19 @@ namespace {
|
||||
|
||||
struct SnotePattern
|
||||
{
|
||||
SnotePattern(SnoteTag tag, char const* expression, unsigned flags = 0)
|
||||
: tag{tag}
|
||||
, expression{expression}
|
||||
, regex{expression, std::regex_constants::ECMAScript | std::regex_constants::optimize}
|
||||
SnotePattern(SnoteTag tag, const char *expression, unsigned flags = 0)
|
||||
: tag{tag}
|
||||
, expression{expression}
|
||||
, regex{expression, std::regex_constants::ECMAScript | std::regex_constants::optimize}
|
||||
{
|
||||
}
|
||||
|
||||
SnoteTag tag;
|
||||
char const* expression;
|
||||
const char *expression;
|
||||
std::regex regex;
|
||||
};
|
||||
|
||||
SnotePattern static const patterns[] =
|
||||
{
|
||||
const SnotePattern static patterns[] = {
|
||||
{SnoteTag::ClientConnecting,
|
||||
R"(^Client connecting: ([^ ]+) \(([^@ ]+)@([^) ]+)\) \[(.*)\] \{([^ ]*)\} <([^ ]*)> \[(.*)\]$)"},
|
||||
|
||||
@ -77,10 +76,10 @@ SnotePattern static const patterns[] =
|
||||
"^\x02([^ ]+)\x02 set vhost ([^ ]+) on the \x02MARKED\x02 account ([^ ]+).$"},
|
||||
};
|
||||
|
||||
static auto setup_database() -> hs_database_t*
|
||||
static auto setup_database() -> hs_database_t *
|
||||
{
|
||||
auto const n = std::size(patterns);
|
||||
std::vector<char const*> expressions;
|
||||
const auto n = std::size(patterns);
|
||||
std::vector<const char *> expressions;
|
||||
std::vector<unsigned> flags(n, HS_FLAG_SINGLEMATCH);
|
||||
std::vector<unsigned> ids;
|
||||
|
||||
@ -93,21 +92,20 @@ static auto setup_database() -> hs_database_t*
|
||||
ids.push_back(i);
|
||||
}
|
||||
|
||||
hs_database_t* db;
|
||||
hs_database_t *db;
|
||||
hs_compile_error *error;
|
||||
hs_platform_info_t *platform = nullptr; // target current platform
|
||||
switch (hs_compile_multi(expressions.data(), flags.data(), ids.data(), expressions.size(), HS_MODE_BLOCK, platform, &db, &error))
|
||||
{
|
||||
case HS_COMPILER_ERROR:
|
||||
{
|
||||
std::string msg = error->message;
|
||||
hs_free_compile_error(error);
|
||||
throw std::runtime_error{std::move(msg)};
|
||||
}
|
||||
case HS_SUCCESS:
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
case HS_COMPILER_ERROR: {
|
||||
std::string msg = error->message;
|
||||
hs_free_compile_error(error);
|
||||
throw std::runtime_error{std::move(msg)};
|
||||
}
|
||||
case HS_SUCCESS:
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
return db;
|
||||
}
|
||||
@ -118,7 +116,7 @@ SnoteCore::SnoteCore()
|
||||
{
|
||||
db_.reset(setup_database());
|
||||
|
||||
hs_scratch_t* scratch = nullptr;
|
||||
hs_scratch_t *scratch = nullptr;
|
||||
if (HS_SUCCESS != hs_alloc_scratch(db_.get(), &scratch))
|
||||
{
|
||||
abort();
|
||||
@ -128,30 +126,29 @@ SnoteCore::SnoteCore()
|
||||
|
||||
auto SnoteCore::match(const IrcMsg &msg) -> std::optional<SnoteMatch>
|
||||
{
|
||||
static char const* const prefix = "*** Notice -- ";
|
||||
static const char *const prefix = "*** Notice -- ";
|
||||
|
||||
auto& args = msg.args;
|
||||
if ("*" != args[0] || !args[1].starts_with(prefix)) {
|
||||
auto &args = msg.args;
|
||||
if ("*" != args[0] || !args[1].starts_with(prefix))
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
auto const message = args[1].substr(strlen(prefix));
|
||||
const auto message = args[1].substr(strlen(prefix));
|
||||
|
||||
unsigned match_id;
|
||||
auto cb = [&match_id](unsigned id, unsigned long long, unsigned long long, unsigned) -> int
|
||||
{
|
||||
auto cb = [&match_id](unsigned id, unsigned long long, unsigned long long, unsigned) -> int {
|
||||
match_id = id;
|
||||
return 1; // stop scanning
|
||||
};
|
||||
|
||||
auto const scan_result =
|
||||
hs_scan(
|
||||
db_.get(),
|
||||
message.data(), message.size(),
|
||||
0, // no flags
|
||||
scratch_.get(),
|
||||
CCallback<decltype(cb)>::invoke, &cb
|
||||
);
|
||||
const auto scan_result = hs_scan(
|
||||
db_.get(),
|
||||
message.data(), message.size(),
|
||||
0, // no flags
|
||||
scratch_.get(),
|
||||
CCallback<decltype(cb)>::invoke, &cb
|
||||
);
|
||||
|
||||
switch (scan_result)
|
||||
{
|
||||
@ -159,9 +156,8 @@ auto SnoteCore::match(const IrcMsg &msg) -> std::optional<SnoteMatch>
|
||||
BOOST_LOG_TRIVIAL(warning) << "Unknown snote: " << message;
|
||||
return std::nullopt;
|
||||
|
||||
case HS_SCAN_TERMINATED:
|
||||
{
|
||||
auto& pattern = patterns[match_id];
|
||||
case HS_SCAN_TERMINATED: {
|
||||
auto &pattern = patterns[match_id];
|
||||
return SnoteMatch{pattern.tag, pattern.regex, message};
|
||||
}
|
||||
|
||||
@ -170,14 +166,15 @@ auto SnoteCore::match(const IrcMsg &msg) -> std::optional<SnoteMatch>
|
||||
}
|
||||
}
|
||||
|
||||
auto SnoteMatch::get_results() -> std::match_results<std::string_view::const_iterator> const&
|
||||
auto SnoteMatch::get_results() -> const std::match_results<std::string_view::const_iterator> &
|
||||
{
|
||||
if (auto results = std::get_if<1>(&components_)) {
|
||||
if (auto results = std::get_if<1>(&components_))
|
||||
{
|
||||
return *results;
|
||||
}
|
||||
|
||||
auto [regex, message] = std::get<0>(components_);
|
||||
auto& results = components_.emplace<1>();
|
||||
auto &results = components_.emplace<1>();
|
||||
if (not std::regex_match(message.begin(), message.end(), results, regex))
|
||||
{
|
||||
// something went wrong - hyperscan disagrees with std::regex
|
||||
@ -186,7 +183,7 @@ auto SnoteMatch::get_results() -> std::match_results<std::string_view::const_ite
|
||||
return results;
|
||||
}
|
||||
|
||||
auto SnoteCore::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))
|
||||
{
|
||||
@ -194,7 +191,7 @@ auto SnoteCore::DbDeleter::operator()(hs_database_t * db) const -> void
|
||||
}
|
||||
}
|
||||
|
||||
auto SnoteCore::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))
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user