]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/asio/example/cpp03/chat/posix_chat_client.cpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / libs / asio / example / cpp03 / chat / posix_chat_client.cpp
CommitLineData
7c673cae
FG
1//
2// posix_chat_client.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 <cstdlib>
12#include <cstring>
13#include <iostream>
14#include <boost/array.hpp>
15#include <boost/bind.hpp>
16#include <boost/asio.hpp>
17#include "chat_message.hpp"
18
19#if defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR)
20
21using boost::asio::ip::tcp;
22namespace posix = boost::asio::posix;
23
24class posix_chat_client
25{
26public:
b32b8144
FG
27 posix_chat_client(boost::asio::io_context& io_context,
28 const tcp::resolver::results_type& endpoints)
29 : socket_(io_context),
30 input_(io_context, ::dup(STDIN_FILENO)),
31 output_(io_context, ::dup(STDOUT_FILENO)),
7c673cae
FG
32 input_buffer_(chat_message::max_body_length)
33 {
b32b8144 34 boost::asio::async_connect(socket_, endpoints,
7c673cae
FG
35 boost::bind(&posix_chat_client::handle_connect, this,
36 boost::asio::placeholders::error));
37 }
38
39private:
40
41 void handle_connect(const boost::system::error_code& error)
42 {
43 if (!error)
44 {
45 // Read the fixed-length header of the next message from the server.
46 boost::asio::async_read(socket_,
47 boost::asio::buffer(read_msg_.data(), chat_message::header_length),
48 boost::bind(&posix_chat_client::handle_read_header, this,
49 boost::asio::placeholders::error));
50
51 // Read a line of input entered by the user.
52 boost::asio::async_read_until(input_, input_buffer_, '\n',
53 boost::bind(&posix_chat_client::handle_read_input, this,
54 boost::asio::placeholders::error,
55 boost::asio::placeholders::bytes_transferred));
56 }
57 }
58
59 void handle_read_header(const boost::system::error_code& error)
60 {
61 if (!error && read_msg_.decode_header())
62 {
63 // Read the variable-length body of the message from the server.
64 boost::asio::async_read(socket_,
65 boost::asio::buffer(read_msg_.body(), read_msg_.body_length()),
66 boost::bind(&posix_chat_client::handle_read_body, this,
67 boost::asio::placeholders::error));
68 }
69 else
70 {
71 close();
72 }
73 }
74
75 void handle_read_body(const boost::system::error_code& error)
76 {
77 if (!error)
78 {
79 // Write out the message we just received, terminated by a newline.
80 static char eol[] = { '\n' };
81 boost::array<boost::asio::const_buffer, 2> buffers = {{
82 boost::asio::buffer(read_msg_.body(), read_msg_.body_length()),
83 boost::asio::buffer(eol) }};
84 boost::asio::async_write(output_, buffers,
85 boost::bind(&posix_chat_client::handle_write_output, this,
86 boost::asio::placeholders::error));
87 }
88 else
89 {
90 close();
91 }
92 }
93
94 void handle_write_output(const boost::system::error_code& error)
95 {
96 if (!error)
97 {
98 // Read the fixed-length header of the next message from the server.
99 boost::asio::async_read(socket_,
100 boost::asio::buffer(read_msg_.data(), chat_message::header_length),
101 boost::bind(&posix_chat_client::handle_read_header, this,
102 boost::asio::placeholders::error));
103 }
104 else
105 {
106 close();
107 }
108 }
109
110 void handle_read_input(const boost::system::error_code& error,
111 std::size_t length)
112 {
113 if (!error)
114 {
115 // Write the message (minus the newline) to the server.
116 write_msg_.body_length(length - 1);
117 input_buffer_.sgetn(write_msg_.body(), length - 1);
118 input_buffer_.consume(1); // Remove newline from input.
119 write_msg_.encode_header();
120 boost::asio::async_write(socket_,
121 boost::asio::buffer(write_msg_.data(), write_msg_.length()),
122 boost::bind(&posix_chat_client::handle_write, this,
123 boost::asio::placeholders::error));
124 }
125 else if (error == boost::asio::error::not_found)
126 {
127 // Didn't get a newline. Send whatever we have.
128 write_msg_.body_length(input_buffer_.size());
129 input_buffer_.sgetn(write_msg_.body(), input_buffer_.size());
130 write_msg_.encode_header();
131 boost::asio::async_write(socket_,
132 boost::asio::buffer(write_msg_.data(), write_msg_.length()),
133 boost::bind(&posix_chat_client::handle_write, this,
134 boost::asio::placeholders::error));
135 }
136 else
137 {
138 close();
139 }
140 }
141
142 void handle_write(const boost::system::error_code& error)
143 {
144 if (!error)
145 {
146 // Read a line of input entered by the user.
147 boost::asio::async_read_until(input_, input_buffer_, '\n',
148 boost::bind(&posix_chat_client::handle_read_input, this,
149 boost::asio::placeholders::error,
150 boost::asio::placeholders::bytes_transferred));
151 }
152 else
153 {
154 close();
155 }
156 }
157
158 void close()
159 {
160 // Cancel all outstanding asynchronous operations.
161 socket_.close();
162 input_.close();
163 output_.close();
164 }
165
166private:
167 tcp::socket socket_;
168 posix::stream_descriptor input_;
169 posix::stream_descriptor output_;
170 chat_message read_msg_;
171 chat_message write_msg_;
172 boost::asio::streambuf input_buffer_;
173};
174
175int main(int argc, char* argv[])
176{
177 try
178 {
179 if (argc != 3)
180 {
181 std::cerr << "Usage: posix_chat_client <host> <port>\n";
182 return 1;
183 }
184
b32b8144 185 boost::asio::io_context io_context;
7c673cae 186
b32b8144
FG
187 tcp::resolver resolver(io_context);
188 tcp::resolver::results_type endpoints = resolver.resolve(argv[1], argv[2]);
7c673cae 189
b32b8144 190 posix_chat_client c(io_context, endpoints);
7c673cae 191
b32b8144 192 io_context.run();
7c673cae
FG
193 }
194 catch (std::exception& e)
195 {
196 std::cerr << "Exception: " << e.what() << "\n";
197 }
198
199 return 0;
200}
201
202#else // defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR)
203int main() {}
204#endif // defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR)