]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/beast/example/websocket/server/stackless/websocket_server_stackless.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 server, stackless coroutine
14 //------------------------------------------------------------------------------
16 #include <boost/beast/core.hpp>
17 #include <boost/beast/websocket.hpp>
18 #include <boost/asio/bind_executor.hpp>
19 #include <boost/asio/coroutine.hpp>
20 #include <boost/asio/strand.hpp>
21 #include <boost/asio/ip/tcp.hpp>
31 using tcp
= boost::asio::ip::tcp
; // from <boost/asio/ip/tcp.hpp>
32 namespace websocket
= boost::beast::websocket
; // from <boost/beast/websocket.hpp>
34 //------------------------------------------------------------------------------
38 fail(boost::system::error_code ec
, char const* what
)
40 std::cerr
<< what
<< ": " << ec
.message() << "\n";
43 // Echoes back all received WebSocket messages
45 : public boost::asio::coroutine
46 , public std::enable_shared_from_this
<session
>
48 websocket::stream
<tcp::socket
> ws_
;
50 boost::asio::io_context::executor_type
> strand_
;
51 boost::beast::multi_buffer buffer_
;
54 // Take ownership of the socket
56 session(tcp::socket socket
)
57 : ws_(std::move(socket
))
58 , strand_(ws_
.get_executor())
62 // Start the asynchronous operation
69 #include <boost/asio/yield.hpp>
72 boost::system::error_code ec
,
73 std::size_t bytes_transferred
)
75 boost::ignore_unused(bytes_transferred
);
78 // Accept the websocket handshake
79 yield ws_
.async_accept(
80 boost::asio::bind_executor(
85 std::placeholders::_1
,
88 return fail(ec
, "accept");
92 // Read a message into our buffer
95 boost::asio::bind_executor(
100 std::placeholders::_1
,
101 std::placeholders::_2
)));
102 if(ec
== websocket::error::closed
)
104 // This indicates that the session was closed
111 ws_
.text(ws_
.got_text());
112 yield ws_
.async_write(
114 boost::asio::bind_executor(
119 std::placeholders::_1
,
120 std::placeholders::_2
)));
122 return fail(ec
, "write");
125 buffer_
.consume(buffer_
.size());
129 #include <boost/asio/unyield.hpp>
132 //------------------------------------------------------------------------------
134 // Accepts incoming connections and launches the sessions
136 : public boost::asio::coroutine
137 , public std::enable_shared_from_this
<listener
>
139 tcp::acceptor acceptor_
;
144 boost::asio::io_context
& ioc
,
145 tcp::endpoint endpoint
)
149 boost::system::error_code ec
;
152 acceptor_
.open(endpoint
.protocol(), ec
);
159 // Allow address reuse
160 acceptor_
.set_option(boost::asio::socket_base::reuse_address(true));
163 fail(ec
, "set_option");
167 // Bind to the server address
168 acceptor_
.bind(endpoint
, ec
);
175 // Start listening for connections
177 boost::asio::socket_base::max_listen_connections
, ec
);
185 // Start accepting incoming connections
189 if(! acceptor_
.is_open())
194 #include <boost/asio/yield.hpp>
196 loop(boost::system::error_code ec
= {})
202 yield acceptor_
.async_accept(
207 std::placeholders::_1
));
214 // Create the session and run it
215 std::make_shared
<session
>(std::move(socket_
))->run();
220 #include <boost/asio/unyield.hpp>
223 //------------------------------------------------------------------------------
225 int main(int argc
, char* argv
[])
227 // Check command line arguments.
231 "Usage: websocket-server-stackless <address> <port> <threads>\n" <<
233 " websocket-server-stackless 0.0.0.0 8080 1\n";
236 auto const address
= boost::asio::ip::make_address(argv
[1]);
237 auto const port
= static_cast<unsigned short>(std::atoi(argv
[2]));
238 auto const threads
= std::max
<int>(1, std::atoi(argv
[3]));
240 // The io_context is required for all I/O
241 boost::asio::io_context ioc
{threads
};
243 // Create and launch a listening port
244 std::make_shared
<listener
>(ioc
, tcp::endpoint
{address
, port
})->run();
246 // Run the I/O service on the requested number of threads
247 std::vector
<std::thread
> v
;
248 v
.reserve(threads
- 1);
249 for(auto i
= threads
- 1; i
> 0; --i
)