]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/beast/example/websocket/server/stackless-ssl/websocket_server_stackless_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, stackless coroutine
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/coroutine.hpp>
23 #include <boost/asio/ip/tcp.hpp>
24 #include <boost/asio/ssl/stream.hpp>
25 #include <boost/asio/strand.hpp>
35 using tcp
= boost::asio::ip::tcp
; // from <boost/asio/ip/tcp.hpp>
36 namespace ssl
= boost::asio::ssl
; // from <boost/asio/ssl.hpp>
37 namespace websocket
= boost::beast::websocket
; // from <boost/beast/websocket.hpp>
39 //------------------------------------------------------------------------------
43 fail(boost::system::error_code ec
, char const* what
)
45 std::cerr
<< what
<< ": " << ec
.message() << "\n";
48 // Echoes back all received WebSocket messages
50 : public boost::asio::coroutine
51 , public std::enable_shared_from_this
<session
>
54 websocket::stream
<ssl::stream
<tcp::socket
&>> ws_
;
56 boost::asio::io_context::executor_type
> strand_
;
57 boost::beast::multi_buffer buffer_
;
60 // Take ownership of the socket
61 session(tcp::socket socket
, ssl::context
& ctx
)
62 : socket_(std::move(socket
))
64 , strand_(ws_
.get_executor())
68 // Start the asynchronous operation
75 #include <boost/asio/yield.hpp>
78 boost::system::error_code ec
,
79 std::size_t bytes_transferred
)
81 boost::ignore_unused(bytes_transferred
);
85 // Perform the SSL handshake
86 yield ws_
.next_layer().async_handshake(
87 ssl::stream_base::server
,
88 boost::asio::bind_executor(
93 std::placeholders::_1
,
96 return fail(ec
, "handshake");
98 // Accept the websocket handshake
99 yield ws_
.async_accept(
100 boost::asio::bind_executor(
105 std::placeholders::_1
,
108 return fail(ec
, "accept");
112 // Read a message into our buffer
113 yield ws_
.async_read(
115 boost::asio::bind_executor(
120 std::placeholders::_1
,
121 std::placeholders::_2
)));
122 if(ec
== websocket::error::closed
)
124 // This indicates that the session was closed
131 ws_
.text(ws_
.got_text());
132 yield ws_
.async_write(
134 boost::asio::bind_executor(
139 std::placeholders::_1
,
140 std::placeholders::_2
)));
142 return fail(ec
, "write");
145 buffer_
.consume(buffer_
.size());
149 #include <boost/asio/unyield.hpp>
152 //------------------------------------------------------------------------------
154 // Accepts incoming connections and launches the sessions
156 : public boost::asio::coroutine
157 , public std::enable_shared_from_this
<listener
>
160 tcp::acceptor acceptor_
;
165 boost::asio::io_context
& ioc
,
167 tcp::endpoint endpoint
)
172 boost::system::error_code ec
;
175 acceptor_
.open(endpoint
.protocol(), ec
);
182 // Bind to the server address
183 acceptor_
.bind(endpoint
, ec
);
190 // Start listening for connections
192 boost::asio::socket_base::max_listen_connections
, ec
);
200 // Start accepting incoming connections
204 if(! acceptor_
.is_open())
209 #include <boost/asio/yield.hpp>
211 loop(boost::system::error_code ec
= {})
217 yield acceptor_
.async_accept(
222 std::placeholders::_1
));
229 // Create the session and run it
230 std::make_shared
<session
>(std::move(socket_
), ctx_
)->run();
235 #include <boost/asio/unyield.hpp>
238 //------------------------------------------------------------------------------
240 int main(int argc
, char* argv
[])
242 // Check command line arguments.
246 "Usage: websocket-server-async-ssl <address> <port> <threads>\n" <<
248 " websocket-server-async-ssl 0.0.0.0 8080 1\n";
251 auto const address
= boost::asio::ip::make_address(argv
[1]);
252 auto const port
= static_cast<unsigned short>(std::atoi(argv
[2]));
253 auto const threads
= std::max
<int>(1, std::atoi(argv
[3]));
255 // The io_context is required for all I/O
256 boost::asio::io_context ioc
{threads
};
258 // The SSL context is required, and holds certificates
259 ssl::context ctx
{ssl::context::sslv23
};
261 // This holds the self-signed certificate used by the server
262 load_server_certificate(ctx
);
264 // Create and launch a listening port
265 std::make_shared
<listener
>(ioc
, ctx
, tcp::endpoint
{address
, port
})->run();
267 // Run the I/O service on the requested number of threads
268 std::vector
<std::thread
> v
;
269 v
.reserve(threads
- 1);
270 for(auto i
= threads
- 1; i
> 0; --i
)