]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/asio/example/cpp03/chat/chat_server.cpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / libs / asio / example / cpp03 / chat / chat_server.cpp
CommitLineData
7c673cae
FG
1//
2// chat_server.cpp
3// ~~~~~~~~~~~~~~~
4//
b32b8144 5// Copyright (c) 2003-2017 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
11#include <algorithm>
12#include <cstdlib>
13#include <deque>
14#include <iostream>
15#include <list>
16#include <set>
17#include <boost/bind.hpp>
18#include <boost/shared_ptr.hpp>
19#include <boost/enable_shared_from_this.hpp>
20#include <boost/asio.hpp>
21#include "chat_message.hpp"
22
23using boost::asio::ip::tcp;
24
25//----------------------------------------------------------------------
26
27typedef std::deque<chat_message> chat_message_queue;
28
29//----------------------------------------------------------------------
30
31class chat_participant
32{
33public:
34 virtual ~chat_participant() {}
35 virtual void deliver(const chat_message& msg) = 0;
36};
37
38typedef boost::shared_ptr<chat_participant> chat_participant_ptr;
39
40//----------------------------------------------------------------------
41
42class chat_room
43{
44public:
45 void join(chat_participant_ptr participant)
46 {
47 participants_.insert(participant);
48 std::for_each(recent_msgs_.begin(), recent_msgs_.end(),
49 boost::bind(&chat_participant::deliver, participant, _1));
50 }
51
52 void leave(chat_participant_ptr participant)
53 {
54 participants_.erase(participant);
55 }
56
57 void deliver(const chat_message& msg)
58 {
59 recent_msgs_.push_back(msg);
60 while (recent_msgs_.size() > max_recent_msgs)
61 recent_msgs_.pop_front();
62
63 std::for_each(participants_.begin(), participants_.end(),
64 boost::bind(&chat_participant::deliver, _1, boost::ref(msg)));
65 }
66
67private:
68 std::set<chat_participant_ptr> participants_;
69 enum { max_recent_msgs = 100 };
70 chat_message_queue recent_msgs_;
71};
72
73//----------------------------------------------------------------------
74
75class chat_session
76 : public chat_participant,
77 public boost::enable_shared_from_this<chat_session>
78{
79public:
b32b8144
FG
80 chat_session(boost::asio::io_context& io_context, chat_room& room)
81 : socket_(io_context),
7c673cae
FG
82 room_(room)
83 {
84 }
85
86 tcp::socket& socket()
87 {
88 return socket_;
89 }
90
91 void start()
92 {
93 room_.join(shared_from_this());
94 boost::asio::async_read(socket_,
95 boost::asio::buffer(read_msg_.data(), chat_message::header_length),
96 boost::bind(
97 &chat_session::handle_read_header, shared_from_this(),
98 boost::asio::placeholders::error));
99 }
100
101 void deliver(const chat_message& msg)
102 {
103 bool write_in_progress = !write_msgs_.empty();
104 write_msgs_.push_back(msg);
105 if (!write_in_progress)
106 {
107 boost::asio::async_write(socket_,
108 boost::asio::buffer(write_msgs_.front().data(),
109 write_msgs_.front().length()),
110 boost::bind(&chat_session::handle_write, shared_from_this(),
111 boost::asio::placeholders::error));
112 }
113 }
114
115 void handle_read_header(const boost::system::error_code& error)
116 {
117 if (!error && read_msg_.decode_header())
118 {
119 boost::asio::async_read(socket_,
120 boost::asio::buffer(read_msg_.body(), read_msg_.body_length()),
121 boost::bind(&chat_session::handle_read_body, shared_from_this(),
122 boost::asio::placeholders::error));
123 }
124 else
125 {
126 room_.leave(shared_from_this());
127 }
128 }
129
130 void handle_read_body(const boost::system::error_code& error)
131 {
132 if (!error)
133 {
134 room_.deliver(read_msg_);
135 boost::asio::async_read(socket_,
136 boost::asio::buffer(read_msg_.data(), chat_message::header_length),
137 boost::bind(&chat_session::handle_read_header, shared_from_this(),
138 boost::asio::placeholders::error));
139 }
140 else
141 {
142 room_.leave(shared_from_this());
143 }
144 }
145
146 void handle_write(const boost::system::error_code& error)
147 {
148 if (!error)
149 {
150 write_msgs_.pop_front();
151 if (!write_msgs_.empty())
152 {
153 boost::asio::async_write(socket_,
154 boost::asio::buffer(write_msgs_.front().data(),
155 write_msgs_.front().length()),
156 boost::bind(&chat_session::handle_write, shared_from_this(),
157 boost::asio::placeholders::error));
158 }
159 }
160 else
161 {
162 room_.leave(shared_from_this());
163 }
164 }
165
166private:
167 tcp::socket socket_;
168 chat_room& room_;
169 chat_message read_msg_;
170 chat_message_queue write_msgs_;
171};
172
173typedef boost::shared_ptr<chat_session> chat_session_ptr;
174
175//----------------------------------------------------------------------
176
177class chat_server
178{
179public:
b32b8144 180 chat_server(boost::asio::io_context& io_context,
7c673cae 181 const tcp::endpoint& endpoint)
b32b8144
FG
182 : io_context_(io_context),
183 acceptor_(io_context, endpoint)
7c673cae
FG
184 {
185 start_accept();
186 }
187
188 void start_accept()
189 {
b32b8144 190 chat_session_ptr new_session(new chat_session(io_context_, room_));
7c673cae
FG
191 acceptor_.async_accept(new_session->socket(),
192 boost::bind(&chat_server::handle_accept, this, new_session,
193 boost::asio::placeholders::error));
194 }
195
196 void handle_accept(chat_session_ptr session,
197 const boost::system::error_code& error)
198 {
199 if (!error)
200 {
201 session->start();
202 }
203
204 start_accept();
205 }
206
207private:
b32b8144 208 boost::asio::io_context& io_context_;
7c673cae
FG
209 tcp::acceptor acceptor_;
210 chat_room room_;
211};
212
213typedef boost::shared_ptr<chat_server> chat_server_ptr;
214typedef std::list<chat_server_ptr> chat_server_list;
215
216//----------------------------------------------------------------------
217
218int main(int argc, char* argv[])
219{
220 try
221 {
222 if (argc < 2)
223 {
224 std::cerr << "Usage: chat_server <port> [<port> ...]\n";
225 return 1;
226 }
227
b32b8144 228 boost::asio::io_context io_context;
7c673cae
FG
229
230 chat_server_list servers;
231 for (int i = 1; i < argc; ++i)
232 {
233 using namespace std; // For atoi.
234 tcp::endpoint endpoint(tcp::v4(), atoi(argv[i]));
b32b8144 235 chat_server_ptr server(new chat_server(io_context, endpoint));
7c673cae
FG
236 servers.push_back(server);
237 }
238
b32b8144 239 io_context.run();
7c673cae
FG
240 }
241 catch (std::exception& e)
242 {
243 std::cerr << "Exception: " << e.what() << "\n";
244 }
245
246 return 0;
247}