From 173182f8e76242c275b159f5bb555c7fddc6cc5d Mon Sep 17 00:00:00 2001 From: Thomas Lindner Date: Fri, 20 May 2022 18:55:22 +0200 Subject: [PATCH] auto-reconnect and don't drop messages --- src/main.cc | 99 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 60 insertions(+), 39 deletions(-) diff --git a/src/main.cc b/src/main.cc index 7a9c7e2..68afe81 100644 --- a/src/main.cc +++ b/src/main.cc @@ -6,11 +6,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -40,6 +42,7 @@ std::string_view DirectionToString(Direction direction) { class Bot { asio::any_io_executor executor; + asio::steady_timer timer; asio::ip::tcp::socket socket; std::string name; std::string pass; @@ -62,6 +65,7 @@ class Bot { Bot::Bot(asio::any_io_executor executor, std::string_view name, std::string_view pass) : executor{executor}, + timer{executor}, socket{executor}, name{name}, pass{pass}, @@ -72,49 +76,66 @@ Bot::Bot(asio::any_io_executor executor, std::string_view name, asio::awaitable Bot::Protocol() { asio::ip::tcp::resolver resolver{executor}; asio::ip::tcp::resolver::query query{"94.45.241.27", "4000"}; - - co_await asio::async_connect( - socket, co_await resolver.async_resolve(query, asio::use_awaitable), - asio::use_awaitable); + auto host = co_await resolver.async_resolve(query, asio::use_awaitable); while (true) { - asio::streambuf buf; - buf.commit(co_await asio::async_read_until(socket, buf, '\n', - asio::use_awaitable)); - std::istream is{&buf}; - std::string field; - char dummy; - std::getline(is, field, '|'); - if (field == "motd") { - std::getline(is, field); - std::cout << "-> MotD: " << field << std::endl; - co_await Join(); - } else if (field == "error") { - std::getline(is, field); - std::cout << "-> Error: " << field << std::endl; - co_return; - } else if (field == "goal") { - is >> goal_x >> dummy >> goal_y; - std::cout << "-> Goal is at (" << goal_x << ", " << goal_y << ")" - << std::endl; - } else if (field == "pos") { - is >> x >> dummy >> y >> dummy >> up >> dummy >> right >> dummy >> down >> - dummy >> left; - std::cout << "-> Position at (" << x << ", " << y << ")" << std::endl; + while (true) { + try { + co_await asio::async_connect(socket, host, asio::use_awaitable); + break; + } catch (std::exception &e) { + std::cout << e.what() << std::endl; + } + timer.expires_after(std::chrono::seconds(1)); + co_await timer.async_wait(asio::use_awaitable); + } + + try { + while (true) { + asio::streambuf buf; + co_await asio::async_read_until(socket, buf, '\n', asio::use_awaitable); + std::istream is{&buf}; + std::string line; + while (std::getline(is, line)) { + std::istringstream iss{line}; + std::string field; + char dummy; + std::getline(iss, field, '|'); + if (field == "motd") { + std::getline(iss, field); + std::cout << "-> MotD: " << field << std::endl; + co_await Join(); + } else if (field == "error") { + std::getline(iss, field); + std::cout << "-> Error: " << field << std::endl; + } else if (field == "goal") { + iss >> goal_x >> dummy >> goal_y; + std::cout << "-> Goal is at (" << goal_x << ", " << goal_y << ")" + << std::endl; + } else if (field == "pos") { + iss >> x >> dummy >> y >> dummy >> up >> dummy >> right >> dummy >> + down >> dummy >> left; + std::cout << "-> Position at (" << x << ", " << y << ")" + << std::endl; #define X(b) (b ? #b ", " : "") - std::cout << " Walls are " << X(up) << X(right) << X(down) << X(left) - << std::endl; + std::cout << " Walls are (" << X(up) << X(right) << X(down) + << X(left) << ")" << std::endl; #undef X - co_await ChooseMove(); - } else if (field == "win" || field == "lose") { - int win, lose; - is >> win >> dummy >> lose; - std::cout << "-> You " << field << '!' << std::endl; - std::cout << " Score: " << win << '/' << lose << std::endl; - } else { - std::cout << "unhandled message: " << field << '|'; - std::getline(is, field); - std::cout << field << std::endl; + co_await ChooseMove(); + } else if (field == "win" || field == "lose") { + int win, lose; + iss >> win >> dummy >> lose; + std::cout << "-> You " << field << '!' << std::endl; + std::cout << " Score: " << win << '/' << lose << std::endl; + } else { + std::cout << "unhandled message: " << field << '|'; + std::getline(iss, field); + std::cout << field << std::endl; + } + } + } + } catch (std::exception &e) { + std::cout << e.what() << std::endl; } } co_return;