]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/beast/example/websocket/client/async-ssl/websocket_client_async_ssl.cpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / libs / beast / example / websocket / client / async-ssl / websocket_client_async_ssl.cpp
1 //
2 // Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
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 SSL client, asynchronous
13 //
14 //------------------------------------------------------------------------------
15
16 #include "example/common/root_certificates.hpp"
17
18 #include <boost/beast/core.hpp>
19 #include <boost/beast/websocket.hpp>
20 #include <boost/beast/websocket/ssl.hpp>
21 #include <boost/asio/connect.hpp>
22 #include <boost/asio/ip/tcp.hpp>
23 #include <boost/asio/ssl/stream.hpp>
24 #include <cstdlib>
25 #include <functional>
26 #include <iostream>
27 #include <memory>
28 #include <string>
29
30 using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
31 namespace ssl = boost::asio::ssl; // from <boost/asio/ssl.hpp>
32 namespace websocket = boost::beast::websocket; // from <boost/beast/websocket.hpp>
33
34 //------------------------------------------------------------------------------
35
36 // Report a failure
37 void
38 fail(boost::system::error_code ec, char const* what)
39 {
40 std::cerr << what << ": " << ec.message() << "\n";
41 }
42
43 // Sends a WebSocket message and prints the response
44 class session : public std::enable_shared_from_this<session>
45 {
46 tcp::resolver resolver_;
47 websocket::stream<ssl::stream<tcp::socket>> ws_;
48 boost::beast::multi_buffer buffer_;
49 std::string host_;
50 std::string text_;
51
52 public:
53 // Resolver and socket require an io_context
54 explicit
55 session(boost::asio::io_context& ioc, ssl::context& ctx)
56 : resolver_(ioc)
57 , ws_(ioc, ctx)
58 {
59 }
60
61 // Start the asynchronous operation
62 void
63 run(
64 char const* host,
65 char const* port,
66 char const* text)
67 {
68 // Save these for later
69 host_ = host;
70 text_ = text;
71
72 // Look up the domain name
73 resolver_.async_resolve(
74 host,
75 port,
76 std::bind(
77 &session::on_resolve,
78 shared_from_this(),
79 std::placeholders::_1,
80 std::placeholders::_2));
81 }
82
83 void
84 on_resolve(
85 boost::system::error_code ec,
86 tcp::resolver::results_type results)
87 {
88 if(ec)
89 return fail(ec, "resolve");
90
91 // Make the connection on the IP address we get from a lookup
92 boost::asio::async_connect(
93 ws_.next_layer().next_layer(),
94 results.begin(),
95 results.end(),
96 std::bind(
97 &session::on_connect,
98 shared_from_this(),
99 std::placeholders::_1));
100 }
101
102 void
103 on_connect(boost::system::error_code ec)
104 {
105 if(ec)
106 return fail(ec, "connect");
107
108 // Perform the SSL handshake
109 ws_.next_layer().async_handshake(
110 ssl::stream_base::client,
111 std::bind(
112 &session::on_ssl_handshake,
113 shared_from_this(),
114 std::placeholders::_1));
115 }
116
117 void
118 on_ssl_handshake(boost::system::error_code ec)
119 {
120 if(ec)
121 return fail(ec, "ssl_handshake");
122
123 // Perform the websocket handshake
124 ws_.async_handshake(host_, "/",
125 std::bind(
126 &session::on_handshake,
127 shared_from_this(),
128 std::placeholders::_1));
129 }
130
131 void
132 on_handshake(boost::system::error_code ec)
133 {
134 if(ec)
135 return fail(ec, "handshake");
136
137 // Send the message
138 ws_.async_write(
139 boost::asio::buffer(text_),
140 std::bind(
141 &session::on_write,
142 shared_from_this(),
143 std::placeholders::_1,
144 std::placeholders::_2));
145 }
146
147 void
148 on_write(
149 boost::system::error_code ec,
150 std::size_t bytes_transferred)
151 {
152 boost::ignore_unused(bytes_transferred);
153
154 if(ec)
155 return fail(ec, "write");
156
157 // Read a message into our buffer
158 ws_.async_read(
159 buffer_,
160 std::bind(
161 &session::on_read,
162 shared_from_this(),
163 std::placeholders::_1,
164 std::placeholders::_2));
165 }
166
167 void
168 on_read(
169 boost::system::error_code ec,
170 std::size_t bytes_transferred)
171 {
172 boost::ignore_unused(bytes_transferred);
173
174 if(ec)
175 return fail(ec, "read");
176
177 // Close the WebSocket connection
178 ws_.async_close(websocket::close_code::normal,
179 std::bind(
180 &session::on_close,
181 shared_from_this(),
182 std::placeholders::_1));
183 }
184
185 void
186 on_close(boost::system::error_code ec)
187 {
188 if(ec)
189 return fail(ec, "close");
190
191 // If we get here then the connection is closed gracefully
192
193 // The buffers() function helps print a ConstBufferSequence
194 std::cout << boost::beast::buffers(buffer_.data()) << std::endl;
195 }
196 };
197
198 //------------------------------------------------------------------------------
199
200 int main(int argc, char** argv)
201 {
202 // Check command line arguments.
203 if(argc != 4)
204 {
205 std::cerr <<
206 "Usage: websocket-client-async-ssl <host> <port> <text>\n" <<
207 "Example:\n" <<
208 " websocket-client-async-ssl echo.websocket.org 443 \"Hello, world!\"\n";
209 return EXIT_FAILURE;
210 }
211 auto const host = argv[1];
212 auto const port = argv[2];
213 auto const text = argv[3];
214
215 // The io_context is required for all I/O
216 boost::asio::io_context ioc;
217
218 // The SSL context is required, and holds certificates
219 ssl::context ctx{ssl::context::sslv23_client};
220
221 // This holds the root certificate used for verification
222 load_root_certificates(ctx);
223
224 // Launch the asynchronous operation
225 std::make_shared<session>(ioc, ctx)->run(host, port, text);
226
227 // Run the I/O service. The call will return when
228 // the get operation is complete.
229 ioc.run();
230
231 return EXIT_SUCCESS;
232 }