| 1 | // |
| 2 | // timeout.cpp |
| 3 | // ~~~~~~~~~~~ |
| 4 | // |
| 5 | // Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) |
| 6 | // |
| 7 | // Distributed under the Boost Software License, Version 1.0. (See accompanying |
| 8 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
| 9 | // |
| 10 | |
| 11 | #include <boost/asio.hpp> |
| 12 | #include <boost/asio/experimental/awaitable_operators.hpp> |
| 13 | |
| 14 | using namespace boost::asio; |
| 15 | using namespace boost::asio::experimental::awaitable_operators; |
| 16 | using time_point = std::chrono::steady_clock::time_point; |
| 17 | using ip::tcp; |
| 18 | |
| 19 | awaitable<void> echo(tcp::socket& sock, time_point& deadline) |
| 20 | { |
| 21 | char data[4196]; |
| 22 | for (;;) |
| 23 | { |
| 24 | deadline = std::chrono::steady_clock::now() + std::chrono::seconds(10); |
| 25 | auto n = co_await sock.async_read_some(buffer(data), use_awaitable); |
| 26 | co_await async_write(sock, buffer(data, n), use_awaitable); |
| 27 | } |
| 28 | } |
| 29 | |
| 30 | awaitable<void> watchdog(time_point& deadline) |
| 31 | { |
| 32 | steady_timer timer(co_await this_coro::executor); |
| 33 | auto now = std::chrono::steady_clock::now(); |
| 34 | while (deadline > now) |
| 35 | { |
| 36 | timer.expires_at(deadline); |
| 37 | co_await timer.async_wait(use_awaitable); |
| 38 | now = std::chrono::steady_clock::now(); |
| 39 | } |
| 40 | throw boost::system::system_error(std::make_error_code(e: std::errc::timed_out)); |
| 41 | } |
| 42 | |
| 43 | awaitable<void> handle_connection(tcp::socket sock) |
| 44 | { |
| 45 | time_point deadline{}; |
| 46 | co_await (echo(sock, deadline) && watchdog(deadline)); |
| 47 | } |
| 48 | |
| 49 | awaitable<void> listen(tcp::acceptor& acceptor) |
| 50 | { |
| 51 | for (;;) |
| 52 | { |
| 53 | co_spawn( |
| 54 | acceptor.get_executor(), |
| 55 | handle_connection(co_await acceptor.async_accept(use_awaitable)), |
| 56 | detached); |
| 57 | } |
| 58 | } |
| 59 | |
| 60 | int main() |
| 61 | { |
| 62 | io_context ctx; |
| 63 | tcp::acceptor acceptor(ctx, {tcp::v4(), 54321}); |
| 64 | co_spawn(ctx, listen(acceptor), detached); |
| 65 | ctx.run(); |
| 66 | } |
| 67 | |