109 lines
2.7 KiB
C++
109 lines
2.7 KiB
C++
#include "connection.hpp"
|
|
|
|
auto Connection::writer_() -> void
|
|
{
|
|
std::vector<boost::asio::const_buffer> 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<void>
|
|
{
|
|
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<ircmsg const&>(&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));
|
|
}
|