#include "connection.hpp" auto Connection::writer_() -> void { std::vector buffers; buffers.reserve(write_strings_.size()); for (auto const& elt : write_strings_) { buffers.push_back(boost::asio::buffer(elt)); } boost::asio::async_write( stream_, buffers, [weak = weak_from_this() ,strings = std::move(write_strings_) ](boost::system::error_code const& error, std::size_t) { if (not error) { if (auto self = weak.lock()) { self->writer(); } } }); write_strings_.clear(); } auto Connection::writer() -> void { if (write_strings_.empty()) { write_timer_.async_wait([weak = weak_from_this()](auto){ if (auto self = weak.lock()) { if (not self->write_strings_.empty()) { self->writer_(); } } }); } else { writer_(); } } auto Connection::connect( boost::asio::io_context & io, Settings settings) -> boost::asio::awaitable { auto self = shared_from_this(); { auto resolver = boost::asio::ip::tcp::resolver{io}; auto const endpoints = co_await resolver.async_resolve(settings.host, settings.service, boost::asio::use_awaitable); auto const endpoint = co_await boost::asio::async_connect(stream_, endpoints, boost::asio::use_awaitable); self->writer(); dispatch(&IrcThread::on_connect); } 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)); if (error) { break; } buffer.add_bytes(n, [this](char * line) { dispatch(&IrcThread::on_msg, parse_irc_message(line)); }); } dispatch(&IrcThread::on_disconnect); } auto Connection::write(std::string message) -> void { auto const need_cancel = write_strings_.empty(); message += "\r\n"; write_strings_.push_back(std::move(message)); if (need_cancel) { write_timer_.cancel_one(); } } auto Connection::write(std::string front, std::string_view last) -> void { auto const is_invalid = [](char x) -> bool { return x == '\0' || x == '\r' || x == '\n'; }; if (last.end() != std::find_if(last.begin(), last.end(), is_invalid)) { throw std::runtime_error{"bad irc argument"}; } front += " :"; front += last; write(std::move(front)); }