]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // |
2 | // udp_server.cpp | |
3 | // ~~~~~~~~~~~~~~ | |
4 | // | |
1e59de90 | 5 | // Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com) |
7c673cae FG |
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 | ||
b32b8144 | 11 | #include <boost/asio/io_context.hpp> |
7c673cae FG |
12 | #include <boost/asio/ip/udp.hpp> |
13 | #include <boost/shared_ptr.hpp> | |
14 | #include <cstdio> | |
15 | #include <cstdlib> | |
16 | #include <cstring> | |
17 | #include <vector> | |
18 | #include "allocator.hpp" | |
19 | ||
20 | using boost::asio::ip::udp; | |
21 | ||
b32b8144 | 22 | #include <boost/asio/yield.hpp> |
7c673cae | 23 | |
b32b8144 | 24 | class udp_server : boost::asio::coroutine |
7c673cae FG |
25 | { |
26 | public: | |
b32b8144 | 27 | udp_server(boost::asio::io_context& io_context, |
7c673cae | 28 | unsigned short port, std::size_t buf_size) : |
b32b8144 | 29 | socket_(io_context, udp::endpoint(udp::v4(), port)), |
7c673cae FG |
30 | buffer_(buf_size) |
31 | { | |
32 | } | |
33 | ||
34 | void operator()(boost::system::error_code ec, std::size_t n = 0) | |
35 | { | |
36 | reenter (this) for (;;) | |
37 | { | |
38 | yield socket_.async_receive_from( | |
39 | boost::asio::buffer(buffer_), | |
40 | sender_, ref(this)); | |
41 | ||
42 | if (!ec) | |
43 | { | |
44 | for (std::size_t i = 0; i < n; ++i) buffer_[i] = ~buffer_[i]; | |
45 | socket_.send_to(boost::asio::buffer(buffer_, n), sender_, 0, ec); | |
46 | } | |
47 | } | |
48 | } | |
49 | ||
50 | friend void* asio_handler_allocate(std::size_t n, udp_server* s) | |
51 | { | |
52 | return s->allocator_.allocate(n); | |
53 | } | |
54 | ||
55 | friend void asio_handler_deallocate(void* p, std::size_t, udp_server* s) | |
56 | { | |
57 | s->allocator_.deallocate(p); | |
58 | } | |
59 | ||
60 | struct ref | |
61 | { | |
62 | explicit ref(udp_server* p) | |
63 | : p_(p) | |
64 | { | |
65 | } | |
66 | ||
67 | void operator()(boost::system::error_code ec, std::size_t n = 0) | |
68 | { | |
69 | (*p_)(ec, n); | |
70 | } | |
71 | ||
72 | private: | |
73 | udp_server* p_; | |
74 | ||
75 | friend void* asio_handler_allocate(std::size_t n, ref* r) | |
76 | { | |
77 | return asio_handler_allocate(n, r->p_); | |
78 | } | |
79 | ||
80 | friend void asio_handler_deallocate(void* p, std::size_t n, ref* r) | |
81 | { | |
82 | asio_handler_deallocate(p, n, r->p_); | |
83 | } | |
84 | }; | |
85 | ||
86 | private: | |
87 | udp::socket socket_; | |
88 | std::vector<unsigned char> buffer_; | |
89 | udp::endpoint sender_; | |
90 | allocator allocator_; | |
91 | }; | |
92 | ||
b32b8144 | 93 | #include <boost/asio/unyield.hpp> |
7c673cae FG |
94 | |
95 | int main(int argc, char* argv[]) | |
96 | { | |
97 | if (argc != 5) | |
98 | { | |
99 | std::fprintf(stderr, | |
100 | "Usage: udp_server <port1> <nports> " | |
101 | "<bufsize> {spin|block}\n"); | |
102 | return 1; | |
103 | } | |
104 | ||
105 | unsigned short first_port = static_cast<unsigned short>(std::atoi(argv[1])); | |
106 | unsigned short num_ports = static_cast<unsigned short>(std::atoi(argv[2])); | |
107 | std::size_t buf_size = std::atoi(argv[3]); | |
108 | bool spin = (std::strcmp(argv[4], "spin") == 0); | |
109 | ||
b32b8144 | 110 | boost::asio::io_context io_context(1); |
7c673cae FG |
111 | std::vector<boost::shared_ptr<udp_server> > servers; |
112 | ||
113 | for (unsigned short i = 0; i < num_ports; ++i) | |
114 | { | |
115 | unsigned short port = first_port + i; | |
b32b8144 | 116 | boost::shared_ptr<udp_server> s(new udp_server(io_context, port, buf_size)); |
7c673cae FG |
117 | servers.push_back(s); |
118 | (*s)(boost::system::error_code()); | |
119 | } | |
120 | ||
121 | if (spin) | |
b32b8144 | 122 | for (;;) io_context.poll(); |
7c673cae | 123 | else |
b32b8144 | 124 | io_context.run(); |
7c673cae | 125 | } |