]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/beast/example/websocket/server/async-ssl/websocket_server_async_ssl.cpp
2 // Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
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)
7 // Official repository: https://github.com/boostorg/beast
10 //------------------------------------------------------------------------------
12 // Example: WebSocket SSL server, asynchronous
14 //------------------------------------------------------------------------------
16 #include "example/common/server_certificate.hpp"
18 #include <boost/beast/core.hpp>
19 #include <boost/beast/websocket.hpp>
20 #include <boost/beast/websocket/ssl.hpp>
21 #include <boost/asio/bind_executor.hpp>
22 #include <boost/asio/strand.hpp>
23 #include <boost/asio/ip/tcp.hpp>
24 #include <boost/asio/ssl/stream.hpp>
34 using tcp
= boost::asio::ip::tcp
; // from <boost/asio/ip/tcp.hpp>
35 namespace ssl
= boost::asio::ssl
; // from <boost/asio/ssl.hpp>
36 namespace websocket
= boost::beast::websocket
; // from <boost/beast/websocket.hpp>
38 //------------------------------------------------------------------------------
42 fail(boost::system::error_code ec
, char const* what
)
44 std::cerr
<< what
<< ": " << ec
.message() << "\n";
47 // Echoes back all received WebSocket messages
48 class session
: public std::enable_shared_from_this
<session
>
51 websocket::stream
<ssl::stream
<tcp::socket
&>> ws_
;
53 boost::asio::io_context::executor_type
> strand_
;
54 boost::beast::multi_buffer buffer_
;
57 // Take ownership of the socket
58 session(tcp::socket socket
, ssl::context
& ctx
)
59 : socket_(std::move(socket
))
61 , strand_(ws_
.get_executor())
65 // Start the asynchronous operation
69 // Perform the SSL handshake
70 ws_
.next_layer().async_handshake(
71 ssl::stream_base::server
,
72 boost::asio::bind_executor(
75 &session::on_handshake
,
77 std::placeholders::_1
)));
81 on_handshake(boost::system::error_code ec
)
84 return fail(ec
, "handshake");
86 // Accept the websocket handshake
88 boost::asio::bind_executor(
93 std::placeholders::_1
)));
97 on_accept(boost::system::error_code ec
)
100 return fail(ec
, "accept");
109 // Read a message into our buffer
112 boost::asio::bind_executor(
117 std::placeholders::_1
,
118 std::placeholders::_2
)));
123 boost::system::error_code ec
,
124 std::size_t bytes_transferred
)
126 boost::ignore_unused(bytes_transferred
);
128 // This indicates that the session was closed
129 if(ec
== websocket::error::closed
)
136 ws_
.text(ws_
.got_text());
139 boost::asio::bind_executor(
144 std::placeholders::_1
,
145 std::placeholders::_2
)));
150 boost::system::error_code ec
,
151 std::size_t bytes_transferred
)
153 boost::ignore_unused(bytes_transferred
);
156 return fail(ec
, "write");
159 buffer_
.consume(buffer_
.size());
166 //------------------------------------------------------------------------------
168 // Accepts incoming connections and launches the sessions
169 class listener
: public std::enable_shared_from_this
<listener
>
172 tcp::acceptor acceptor_
;
177 boost::asio::io_context
& ioc
,
179 tcp::endpoint endpoint
)
184 boost::system::error_code ec
;
187 acceptor_
.open(endpoint
.protocol(), ec
);
194 // Bind to the server address
195 acceptor_
.bind(endpoint
, ec
);
202 // Start listening for connections
204 boost::asio::socket_base::max_listen_connections
, ec
);
212 // Start accepting incoming connections
216 if(! acceptor_
.is_open())
224 acceptor_
.async_accept(
227 &listener::on_accept
,
229 std::placeholders::_1
));
233 on_accept(boost::system::error_code ec
)
241 // Create the session and run it
242 std::make_shared
<session
>(std::move(socket_
), ctx_
)->run();
245 // Accept another connection
250 //------------------------------------------------------------------------------
252 int main(int argc
, char* argv
[])
254 // Check command line arguments.
258 "Usage: websocket-server-async-ssl <address> <port> <threads>\n" <<
260 " websocket-server-async-ssl 0.0.0.0 8080 1\n";
263 auto const address
= boost::asio::ip::make_address(argv
[1]);
264 auto const port
= static_cast<unsigned short>(std::atoi(argv
[2]));
265 auto const threads
= std::max
<int>(1, std::atoi(argv
[3]));
267 // The io_context is required for all I/O
268 boost::asio::io_context ioc
{threads
};
270 // The SSL context is required, and holds certificates
271 ssl::context ctx
{ssl::context::sslv23
};
273 // This holds the self-signed certificate used by the server
274 load_server_certificate(ctx
);
276 // Create and launch a listening port
277 std::make_shared
<listener
>(ioc
, ctx
, tcp::endpoint
{address
, port
})->run();
279 // Run the I/O service on the requested number of threads
280 std::vector
<std::thread
> v
;
281 v
.reserve(threads
- 1);
282 for(auto i
= threads
- 1; i
> 0; --i
)