xbot/connection.cpp

110 lines
2.7 KiB
C++
Raw Normal View History

2023-11-22 19:59:34 -08:00
#include "connection.hpp"
2023-11-27 19:09:45 -08:00
#include "linebuffer.hpp"
2023-11-25 09:22:55 -08:00
Connection::Connection(boost::asio::io_context & io)
: stream_{io}
, write_timer_{io, std::chrono::steady_clock::time_point::max()}
{
}
2023-11-22 19:59:34 -08:00
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,
2023-11-25 09:22:55 -08:00
std::string host,
std::string port
) -> boost::asio::awaitable<void>
2023-11-22 19:59:34 -08:00
{
2023-11-25 09:22:55 -08:00
using namespace std::placeholders;
// keep connection alive while coroutine is active
auto const self = shared_from_this();
2023-11-22 19:59:34 -08:00
{
auto resolver = boost::asio::ip::tcp::resolver{io};
2023-11-25 09:22:55 -08:00
auto const endpoints = co_await resolver.async_resolve(host, port, boost::asio::use_awaitable);
2023-11-22 19:59:34 -08:00
auto const endpoint = co_await boost::asio::async_connect(stream_, endpoints, boost::asio::use_awaitable);
2023-11-25 09:22:55 -08:00
make_event<ConnectEvent>();
2023-11-22 19:59:34 -08:00
}
2023-11-25 09:22:55 -08:00
self->writer();
2023-11-22 19:59:34 -08:00
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) {
2023-11-27 14:12:20 -08:00
std::cout << "RECV: " << line << std::endl;
2023-11-25 09:22:55 -08:00
make_event<LineEvent>(line);
2023-11-22 19:59:34 -08:00
});
}
2023-11-25 09:22:55 -08:00
make_event<DisconnectEvent>();
2023-11-22 19:59:34 -08:00
}
2023-11-26 19:59:12 -08:00
auto Connection::write_line(std::string message) -> void
2023-11-22 19:59:34 -08:00
{
2023-11-27 14:12:20 -08:00
std::cout << "SEND: " << message << std::endl;
2023-11-26 19:59:12 -08:00
message += "\r\n";
2023-11-22 19:59:34 -08:00
auto const need_cancel = write_strings_.empty();
write_strings_.push_back(std::move(message));
if (need_cancel)
{
write_timer_.cancel_one();
}
}
2023-11-25 09:22:55 -08:00
auto Connection::close() -> void
{
stream_.close();
2023-11-27 14:12:20 -08:00
}