98 lines
2.5 KiB
C++
98 lines
2.5 KiB
C++
#pragma once
|
|
|
|
#include "irc_thread.hpp"
|
|
#include "ircmsg.hpp"
|
|
#include "linebuffer.hpp"
|
|
#include "settings.hpp"
|
|
|
|
#include <boost/asio.hpp>
|
|
|
|
#include <chrono>
|
|
#include <coroutine>
|
|
#include <iostream>
|
|
#include <list>
|
|
#include <memory>
|
|
#include <string>
|
|
#include <string_view>
|
|
#include <tuple>
|
|
#include <utility>
|
|
#include <variant>
|
|
#include <vector>
|
|
|
|
class Connection : public std::enable_shared_from_this<Connection>
|
|
{
|
|
boost::asio::ip::tcp::socket stream_;
|
|
boost::asio::steady_timer write_timer_;
|
|
|
|
std::list<std::string> write_strings_;
|
|
std::vector<std::unique_ptr<IrcThread>> threads_;
|
|
|
|
auto writer() -> void;
|
|
auto writer_() -> void;
|
|
|
|
template <typename... Args>
|
|
auto dispatch(
|
|
IrcThread::callback_result (IrcThread::* method)(Args...),
|
|
Args... args
|
|
) -> void
|
|
{
|
|
std::vector<std::unique_ptr<IrcThread>> work;
|
|
work.swap(threads_);
|
|
std::sort(work.begin(), work.end(), [](auto const& a, auto const& b) { return a->priority() < b->priority(); });
|
|
|
|
std::size_t const n = work.size();
|
|
for (std::size_t i = 0; i < n; i++)
|
|
{
|
|
auto const [thread_outcome, msg_outcome] = (work[i].get()->*method)(args...);
|
|
if (thread_outcome == ThreadOutcome::Continue)
|
|
{
|
|
threads_.push_back(std::move(work[i]));
|
|
}
|
|
if (msg_outcome == EventOutcome::Consume)
|
|
{
|
|
std::move(work.begin() + i + 1, work.end(), std::back_inserter(threads_));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
public:
|
|
Connection(boost::asio::io_context & io)
|
|
: stream_{io}
|
|
, write_timer_{io, std::chrono::steady_clock::time_point::max()}
|
|
{
|
|
}
|
|
|
|
auto listen(std::unique_ptr<IrcThread> thread) -> void
|
|
{
|
|
threads_.push_back(std::move(thread));
|
|
}
|
|
|
|
auto write(std::string front, std::string_view last) -> void;
|
|
|
|
template <typename... Args>
|
|
auto write(std::string front, std::string_view next, Args ...rest) -> void
|
|
{
|
|
auto const is_invalid = [](char x) -> bool {
|
|
return x == '\0' || x == '\r' || x == '\n' || x == ' ';
|
|
};
|
|
|
|
if (next.empty() || next.end() != std::find_if(next.begin(), next.end(), is_invalid))
|
|
{
|
|
throw std::runtime_error{"bad irc argument"};
|
|
}
|
|
|
|
front += " ";
|
|
front += next;
|
|
write(std::move(front), rest...);
|
|
}
|
|
|
|
auto write(std::string message) -> void;
|
|
|
|
auto connect(
|
|
boost::asio::io_context & io,
|
|
Settings settings
|
|
) -> boost::asio::awaitable<void>;
|
|
};
|
|
|