• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // range_based_for.cpp
3 // ~~~~~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2020 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/co_spawn.hpp>
12 #include <boost/asio/detached.hpp>
13 #include <boost/asio/io_context.hpp>
14 #include <boost/asio/ip/tcp.hpp>
15 #include <boost/asio/signal_set.hpp>
16 #include <boost/asio/write.hpp>
17 #include <cstdio>
18 
19 using boost::asio::ip::tcp;
20 using boost::asio::awaitable;
21 using boost::asio::co_spawn;
22 using boost::asio::detached;
23 using boost::asio::use_awaitable;
24 
25 class connection_iter
26 {
27   friend class connections;
28   tcp::acceptor* acceptor_ = nullptr;
29   tcp::socket socket_;
30 
connection_iter(tcp::acceptor & a,tcp::socket s)31   connection_iter(tcp::acceptor& a, tcp::socket s)
32     : acceptor_(&a), socket_(std::move(s)) {}
33 
34 public:
operator *()35   tcp::socket operator*()
36   {
37     return std::move(socket_);
38   }
39 
operator ++()40   awaitable<void> operator++()
41   {
42     socket_ = co_await acceptor_->async_accept(use_awaitable);
43   }
44 
operator ==(const connection_iter &) const45   bool operator==(const connection_iter&) const noexcept
46   {
47     return false;
48   }
49 
operator !=(const connection_iter &) const50   bool operator!=(const connection_iter&) const noexcept
51   {
52     return true;
53   }
54 };
55 
56 class connections
57 {
58   tcp::acceptor& acceptor_;
59 
60 public:
connections(tcp::acceptor & a)61   explicit connections(tcp::acceptor& a) : acceptor_(a) {}
62 
begin()63   awaitable<connection_iter> begin()
64   {
65     tcp::socket s = co_await acceptor_.async_accept(use_awaitable);
66     co_return connection_iter(acceptor_, std::move(s));
67   }
68 
end()69   connection_iter end()
70   {
71     return connection_iter(acceptor_,
72         tcp::socket(acceptor_.get_executor()));
73   }
74 };
75 
listener(tcp::acceptor acceptor)76 awaitable<void> listener(tcp::acceptor acceptor)
77 {
78   for co_await (tcp::socket s : connections(acceptor))
79   {
80     co_await boost::asio::async_write(s, boost::asio::buffer("hello\r\n", 7), use_awaitable);
81   }
82 }
83 
main()84 int main()
85 {
86   try
87   {
88     boost::asio::io_context io_context(1);
89 
90     boost::asio::signal_set signals(io_context, SIGINT, SIGTERM);
91     signals.async_wait([&](auto, auto){ io_context.stop(); });
92 
93     tcp::acceptor acceptor(io_context, {tcp::v4(), 55555});
94     co_spawn(io_context, listener(std::move(acceptor)), detached);
95 
96     io_context.run();
97   }
98   catch (std::exception& e)
99   {
100     std::printf("Exception: %s\n", e.what());
101   }
102 }
103