]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/beast/example/websocket/client/async/websocket_client_async.cpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / libs / beast / example / websocket / client / async / websocket_client_async.cpp
CommitLineData
b32b8144 1//
92f5a8d4 2// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
b32b8144
FG
3//
4// Distributed under the Boost Software License, Version 1.0. (See accompanying
5// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6//
7// Official repository: https://github.com/boostorg/beast
8//
9
10//------------------------------------------------------------------------------
11//
12// Example: WebSocket client, asynchronous
13//
14//------------------------------------------------------------------------------
15
16#include <boost/beast/core.hpp>
17#include <boost/beast/websocket.hpp>
92f5a8d4 18#include <boost/asio/strand.hpp>
b32b8144
FG
19#include <cstdlib>
20#include <functional>
21#include <iostream>
22#include <memory>
23#include <string>
24
92f5a8d4
TL
25namespace beast = boost::beast; // from <boost/beast.hpp>
26namespace http = beast::http; // from <boost/beast/http.hpp>
27namespace websocket = beast::websocket; // from <boost/beast/websocket.hpp>
28namespace net = boost::asio; // from <boost/asio.hpp>
29using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
b32b8144
FG
30
31//------------------------------------------------------------------------------
32
33// Report a failure
34void
92f5a8d4 35fail(beast::error_code ec, char const* what)
b32b8144
FG
36{
37 std::cerr << what << ": " << ec.message() << "\n";
38}
39
40// Sends a WebSocket message and prints the response
41class session : public std::enable_shared_from_this<session>
42{
43 tcp::resolver resolver_;
92f5a8d4
TL
44 websocket::stream<beast::tcp_stream> ws_;
45 beast::flat_buffer buffer_;
b32b8144
FG
46 std::string host_;
47 std::string text_;
48
49public:
50 // Resolver and socket require an io_context
51 explicit
92f5a8d4
TL
52 session(net::io_context& ioc)
53 : resolver_(net::make_strand(ioc))
54 , ws_(net::make_strand(ioc))
b32b8144
FG
55 {
56 }
57
58 // Start the asynchronous operation
59 void
60 run(
61 char const* host,
62 char const* port,
63 char const* text)
64 {
65 // Save these for later
66 host_ = host;
67 text_ = text;
68
69 // Look up the domain name
70 resolver_.async_resolve(
71 host,
72 port,
92f5a8d4 73 beast::bind_front_handler(
b32b8144 74 &session::on_resolve,
92f5a8d4 75 shared_from_this()));
b32b8144
FG
76 }
77
78 void
79 on_resolve(
92f5a8d4 80 beast::error_code ec,
b32b8144
FG
81 tcp::resolver::results_type results)
82 {
83 if(ec)
84 return fail(ec, "resolve");
85
92f5a8d4
TL
86 // Set the timeout for the operation
87 beast::get_lowest_layer(ws_).expires_after(std::chrono::seconds(30));
88
b32b8144 89 // Make the connection on the IP address we get from a lookup
92f5a8d4
TL
90 beast::get_lowest_layer(ws_).async_connect(
91 results,
92 beast::bind_front_handler(
b32b8144 93 &session::on_connect,
92f5a8d4 94 shared_from_this()));
b32b8144
FG
95 }
96
97 void
92f5a8d4 98 on_connect(beast::error_code ec, tcp::resolver::results_type::endpoint_type)
b32b8144
FG
99 {
100 if(ec)
101 return fail(ec, "connect");
102
92f5a8d4
TL
103 // Turn off the timeout on the tcp_stream, because
104 // the websocket stream has its own timeout system.
105 beast::get_lowest_layer(ws_).expires_never();
106
107 // Set suggested timeout settings for the websocket
108 ws_.set_option(
109 websocket::stream_base::timeout::suggested(
110 beast::role_type::client));
111
112 // Set a decorator to change the User-Agent of the handshake
113 ws_.set_option(websocket::stream_base::decorator(
114 [](websocket::request_type& req)
115 {
116 req.set(http::field::user_agent,
117 std::string(BOOST_BEAST_VERSION_STRING) +
118 " websocket-client-async");
119 }));
120
b32b8144
FG
121 // Perform the websocket handshake
122 ws_.async_handshake(host_, "/",
92f5a8d4 123 beast::bind_front_handler(
b32b8144 124 &session::on_handshake,
92f5a8d4 125 shared_from_this()));
b32b8144
FG
126 }
127
128 void
92f5a8d4 129 on_handshake(beast::error_code ec)
b32b8144
FG
130 {
131 if(ec)
132 return fail(ec, "handshake");
133
134 // Send the message
135 ws_.async_write(
92f5a8d4
TL
136 net::buffer(text_),
137 beast::bind_front_handler(
b32b8144 138 &session::on_write,
92f5a8d4 139 shared_from_this()));
b32b8144
FG
140 }
141
142 void
143 on_write(
92f5a8d4 144 beast::error_code ec,
b32b8144
FG
145 std::size_t bytes_transferred)
146 {
147 boost::ignore_unused(bytes_transferred);
148
149 if(ec)
150 return fail(ec, "write");
151
152 // Read a message into our buffer
153 ws_.async_read(
154 buffer_,
92f5a8d4 155 beast::bind_front_handler(
b32b8144 156 &session::on_read,
92f5a8d4 157 shared_from_this()));
b32b8144
FG
158 }
159
160 void
161 on_read(
92f5a8d4 162 beast::error_code ec,
b32b8144
FG
163 std::size_t bytes_transferred)
164 {
165 boost::ignore_unused(bytes_transferred);
166
167 if(ec)
168 return fail(ec, "read");
169
170 // Close the WebSocket connection
171 ws_.async_close(websocket::close_code::normal,
92f5a8d4 172 beast::bind_front_handler(
b32b8144 173 &session::on_close,
92f5a8d4 174 shared_from_this()));
b32b8144
FG
175 }
176
177 void
92f5a8d4 178 on_close(beast::error_code ec)
b32b8144
FG
179 {
180 if(ec)
181 return fail(ec, "close");
182
183 // If we get here then the connection is closed gracefully
184
92f5a8d4
TL
185 // The make_printable() function helps print a ConstBufferSequence
186 std::cout << beast::make_printable(buffer_.data()) << std::endl;
b32b8144
FG
187 }
188};
189
190//------------------------------------------------------------------------------
191
192int main(int argc, char** argv)
193{
194 // Check command line arguments.
195 if(argc != 4)
196 {
197 std::cerr <<
198 "Usage: websocket-client-async <host> <port> <text>\n" <<
199 "Example:\n" <<
200 " websocket-client-async echo.websocket.org 80 \"Hello, world!\"\n";
201 return EXIT_FAILURE;
202 }
203 auto const host = argv[1];
204 auto const port = argv[2];
205 auto const text = argv[3];
206
207 // The io_context is required for all I/O
92f5a8d4 208 net::io_context ioc;
b32b8144
FG
209
210 // Launch the asynchronous operation
211 std::make_shared<session>(ioc)->run(host, port, text);
212
213 // Run the I/O service. The call will return when
11fdf7f2 214 // the socket is closed.
b32b8144
FG
215 ioc.run();
216
217 return EXIT_SUCCESS;
218}