Use tcp_stream in WebSocket server examples

This commit is contained in:
Vinnie Falco
2019-02-09 22:30:54 -08:00
parent 920909673a
commit 6ee1a88292
15 changed files with 215 additions and 283 deletions

View File

@ -5,6 +5,7 @@ Version 213:
* Use timeouts in HTTP server examples
* Use timeouts in HTTP client examples
* Use tcp_stream in WebSocket client examples
* Use tcp_stream in WebSocket server examples
--------------------------------------------------------------------------------

View File

@ -18,10 +18,8 @@
#include <boost/beast/core.hpp>
#include <boost/beast/websocket.hpp>
#include <boost/beast/websocket/ssl.hpp>
#include <boost/asio/bind_executor.hpp>
#include <boost/beast/_experimental/core/ssl_stream.hpp>
#include <boost/asio/strand.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/ssl/stream.hpp>
#include <algorithm>
#include <cstdlib>
#include <functional>
@ -50,18 +48,14 @@ fail(beast::error_code ec, char const* what)
// Echoes back all received WebSocket messages
class session : public std::enable_shared_from_this<session>
{
tcp::socket socket_;
websocket::stream<ssl::stream<tcp::socket&>> ws_;
net::strand<
net::io_context::executor_type> strand_;
websocket::stream<beast::ssl_stream<
beast::tcp_stream<net::io_context::strand>>> ws_;
beast::multi_buffer buffer_;
public:
// Take ownership of the socket
session(tcp::socket socket, ssl::context& ctx)
: socket_(std::move(socket))
, ws_(socket_, ctx)
, strand_(ws_.get_executor())
: ws_(std::move(socket), ctx)
{
}
@ -69,15 +63,16 @@ public:
void
run()
{
// Set the timeout.
beast::get_lowest_layer(ws_).expires_after(std::chrono::seconds(30));
// Perform the SSL handshake
ws_.next_layer().async_handshake(
ssl::stream_base::server,
net::bind_executor(
strand_,
std::bind(
&session::on_handshake,
shared_from_this(),
std::placeholders::_1)));
std::placeholders::_1));
}
void
@ -88,12 +83,10 @@ public:
// Accept the websocket handshake
ws_.async_accept(
net::bind_executor(
strand_,
std::bind(
&session::on_accept,
shared_from_this(),
std::placeholders::_1)));
std::placeholders::_1));
}
void
@ -112,13 +105,11 @@ public:
// Read a message into our buffer
ws_.async_read(
buffer_,
net::bind_executor(
strand_,
std::bind(
&session::on_read,
shared_from_this(),
std::placeholders::_1,
std::placeholders::_2)));
std::placeholders::_2));
}
void
@ -139,13 +130,11 @@ public:
ws_.text(ws_.got_text());
ws_.async_write(
buffer_.data(),
net::bind_executor(
strand_,
std::bind(
&session::on_write,
shared_from_this(),
std::placeholders::_1,
std::placeholders::_2)));
std::placeholders::_2));
}
void
@ -173,7 +162,6 @@ class listener : public std::enable_shared_from_this<listener>
{
ssl::context& ctx_;
tcp::acceptor acceptor_;
tcp::socket socket_;
public:
listener(
@ -182,7 +170,6 @@ public:
tcp::endpoint endpoint)
: ctx_(ctx)
, acceptor_(ioc)
, socket_(ioc)
{
beast::error_code ec;
@ -233,15 +220,15 @@ public:
do_accept()
{
acceptor_.async_accept(
socket_,
std::bind(
&listener::on_accept,
shared_from_this(),
std::placeholders::_1));
std::placeholders::_1,
std::placeholders::_2));
}
void
on_accept(beast::error_code ec)
on_accept(beast::error_code ec, tcp::socket socket)
{
if(ec)
{
@ -250,7 +237,7 @@ public:
else
{
// Create the session and run it
std::make_shared<session>(std::move(socket_), ctx_)->run();
std::make_shared<session>(std::move(socket), ctx_)->run();
}
// Accept another connection

View File

@ -15,9 +15,7 @@
#include <boost/beast/core.hpp>
#include <boost/beast/websocket.hpp>
#include <boost/asio/bind_executor.hpp>
#include <boost/asio/strand.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <algorithm>
#include <cstdlib>
#include <functional>
@ -45,9 +43,7 @@ fail(beast::error_code ec, char const* what)
// Echoes back all received WebSocket messages
class session : public std::enable_shared_from_this<session>
{
websocket::stream<tcp::socket> ws_;
net::strand<
net::io_context::executor_type> strand_;
websocket::stream<beast::tcp_stream<net::io_context::strand>> ws_;
beast::multi_buffer buffer_;
public:
@ -55,7 +51,6 @@ public:
explicit
session(tcp::socket socket)
: ws_(std::move(socket))
, strand_(ws_.get_executor())
{
}
@ -65,12 +60,10 @@ public:
{
// Accept the websocket handshake
ws_.async_accept(
net::bind_executor(
strand_,
std::bind(
&session::on_accept,
shared_from_this(),
std::placeholders::_1)));
std::placeholders::_1));
}
void
@ -89,13 +82,11 @@ public:
// Read a message into our buffer
ws_.async_read(
buffer_,
net::bind_executor(
strand_,
std::bind(
&session::on_read,
shared_from_this(),
std::placeholders::_1,
std::placeholders::_2)));
std::placeholders::_2));
}
void
@ -116,13 +107,11 @@ public:
ws_.text(ws_.got_text());
ws_.async_write(
buffer_.data(),
net::bind_executor(
strand_,
std::bind(
&session::on_write,
shared_from_this(),
std::placeholders::_1,
std::placeholders::_2)));
std::placeholders::_2));
}
void
@ -149,14 +138,12 @@ public:
class listener : public std::enable_shared_from_this<listener>
{
tcp::acceptor acceptor_;
tcp::socket socket_;
public:
listener(
net::io_context& ioc,
tcp::endpoint endpoint)
: acceptor_(ioc)
, socket_(ioc)
{
beast::error_code ec;
@ -207,15 +194,15 @@ public:
do_accept()
{
acceptor_.async_accept(
socket_,
std::bind(
&listener::on_accept,
shared_from_this(),
std::placeholders::_1));
std::placeholders::_1,
std::placeholders::_2));
}
void
on_accept(beast::error_code ec)
on_accept(beast::error_code ec, tcp::socket socket)
{
if(ec)
{
@ -224,7 +211,7 @@ public:
else
{
// Create the session and run it
std::make_shared<session>(std::move(socket_))->run();
std::make_shared<session>(std::move(socket))->run();
}
// Accept another connection

View File

@ -190,11 +190,10 @@ handle_request(
http_session::
http_session(
tcp::socket socket,
tcp::socket&& socket,
boost::shared_ptr<shared_state> const& state)
: socket_(std::move(socket))
: stream_(std::move(socket))
, state_(state)
, strand_(socket_.get_executor())
{
}
@ -202,14 +201,16 @@ void
http_session::
run()
{
// Set the timeout.
stream_.expires_after(std::chrono::seconds(30));
// Read a request
http::async_read(socket_, buffer_, req_,
net::bind_executor(strand_,
http::async_read(stream_, buffer_, req_,
std::bind(
&http_session::on_read,
shared_from_this(),
std::placeholders::_1,
std::placeholders::_2)));
std::placeholders::_2));
}
// Report a failure
@ -239,13 +240,12 @@ operator()(http::message<isRequest, Body, Fields>&& msg) const
// Write the response
auto self = self_.shared_from_this();
http::async_write(
self_.socket_,
self_.stream_,
*sp,
net::bind_executor(self_.strand_,
[self, sp](beast::error_code ec, std::size_t bytes)
{
self->on_write(ec, bytes, sp->need_eof());
}));
});
}
void
@ -255,7 +255,7 @@ on_read(beast::error_code ec, std::size_t)
// This means they closed the connection
if(ec == http::error::end_of_stream)
{
socket_.shutdown(tcp::socket::shutdown_send, ec);
stream_.socket().shutdown(tcp::socket::shutdown_send, ec);
return;
}
@ -268,7 +268,8 @@ on_read(beast::error_code ec, std::size_t)
{
// Create a WebSocket session by transferring the socket
boost::make_shared<websocket_session>(
std::move(socket_), state_)->run(std::move(req_));
std::move(stream_.release_socket()),
state_)->run(std::move(req_));
return;
}
@ -292,23 +293,21 @@ on_read(beast::error_code ec, std::size_t)
#if 0
// NOTE This causes an ICE in gcc 7.3
// Write the response
http::async_write(this->socket_, *sp,
net::bind_executor(strand_,
http::async_write(this->stream_, *sp,
[self = shared_from_this(), sp](
beast::error_code ec, std::size_t bytes)
{
self->on_write(ec, bytes, sp->need_eof());
}));
});
#else
// Write the response
auto self = shared_from_this();
http::async_write(this->socket_, *sp,
net::bind_executor(strand_,
http::async_write(stream_, *sp,
[self, sp](
beast::error_code ec, std::size_t bytes)
{
self->on_write(ec, bytes, sp->need_eof());
}));
});
#endif
});
#else
@ -336,7 +335,7 @@ on_write(beast::error_code ec, std::size_t, bool close)
{
// This means we should close the connection, usually because
// the response indicated the "Connection: close" semantic.
socket_.shutdown(tcp::socket::shutdown_send, ec);
stream_.socket().shutdown(tcp::socket::shutdown_send, ec);
return;
}
@ -344,8 +343,11 @@ on_write(beast::error_code ec, std::size_t, bool close)
// otherwise the read behavior is undefined.
req_ = {};
// Set the timeout.
stream_.expires_after(std::chrono::seconds(30));
// Read another request
http::async_read(socket_, buffer_, req_,
http::async_read(stream_, buffer_, req_,
std::bind(
&http_session::on_read,
shared_from_this(),

View File

@ -21,11 +21,10 @@
*/
class http_session : public boost::enable_shared_from_this<http_session>
{
tcp::socket socket_;
beast::tcp_stream<net::io_context::strand> stream_;
beast::flat_buffer buffer_;
boost::shared_ptr<shared_state> state_;
http::request<http::string_body> req_;
net::strand<net::io_context::executor_type> strand_;
struct send_lambda
{
@ -48,7 +47,7 @@ class http_session : public boost::enable_shared_from_this<http_session>
public:
http_session(
tcp::socket socket,
tcp::socket&& socket,
boost::shared_ptr<shared_state> const& state);
void run();

View File

@ -17,7 +17,6 @@ listener(
tcp::endpoint endpoint,
boost::shared_ptr<shared_state> const& state)
: acceptor_(ioc)
, socket_(ioc)
, state_(state)
{
beast::error_code ec;
@ -62,11 +61,11 @@ run()
{
// Start accepting a connection
acceptor_.async_accept(
socket_,
std::bind(
&listener::on_accept,
shared_from_this(),
std::placeholders::_1));
std::placeholders::_1,
std::placeholders::_2));
}
// Report a failure
@ -83,21 +82,21 @@ fail(beast::error_code ec, char const* what)
// Handle a connection
void
listener::
on_accept(beast::error_code ec)
on_accept(beast::error_code ec, tcp::socket socket)
{
if(ec)
return fail(ec, "accept");
else
// Launch a new session for this connection
boost::make_shared<http_session>(
std::move(socket_),
std::move(socket),
state_)->run();
// Accept another connection
acceptor_.async_accept(
socket_,
std::bind(
&listener::on_accept,
shared_from_this(),
std::placeholders::_1));
std::placeholders::_1,
std::placeholders::_2));
}

View File

@ -23,11 +23,10 @@ class shared_state;
class listener : public boost::enable_shared_from_this<listener>
{
tcp::acceptor acceptor_;
tcp::socket socket_;
boost::shared_ptr<shared_state> state_;
void fail(beast::error_code ec, char const* what);
void on_accept(beast::error_code ec);
void on_accept(beast::error_code ec, tcp::socket socket);
public:
listener(

View File

@ -35,7 +35,7 @@ main(int argc, char* argv[])
std::cerr <<
"Usage: websocket-chat-multi <address> <port> <doc_root> <threads>\n" <<
"Example:\n" <<
" websocket-chat-server 0.0.0.0 8080 .\n";
" websocket-chat-server 0.0.0.0 8080 . 5\n";
return EXIT_FAILURE;
}
auto address = net::ip::make_address(argv[1]);

View File

@ -12,11 +12,10 @@
websocket_session::
websocket_session(
tcp::socket socket,
tcp::socket&& socket,
boost::shared_ptr<shared_state> const& state)
: ws_(std::move(socket))
, state_(state)
, strand_(ws_.get_executor())
{
}
@ -53,12 +52,11 @@ on_accept(beast::error_code ec)
// Read a message
ws_.async_read(
buffer_,
net::bind_executor(strand_,
std::bind(
&websocket_session::on_read,
shared_from_this(),
std::placeholders::_1,
std::placeholders::_2)));
std::placeholders::_2));
}
void
@ -78,12 +76,11 @@ on_read(beast::error_code ec, std::size_t)
// Read another message
ws_.async_read(
buffer_,
net::bind_executor(strand_,
std::bind(
&websocket_session::on_read,
shared_from_this(),
std::placeholders::_1,
std::placeholders::_2)));
std::placeholders::_2));
}
void
@ -93,13 +90,13 @@ send(boost::shared_ptr<std::string const> const& ss)
// Get on the strand if we aren't already,
// otherwise we will concurrently access
// objects which are not thread-safe.
if(! strand_.running_in_this_thread())
if(! ws_.get_executor().running_in_this_thread())
return net::post(
net::bind_executor(strand_,
ws_.get_executor(),
std::bind(
&websocket_session::send,
shared_from_this(),
ss)));
ss));
// Always add to queue
queue_.push_back(ss);
@ -111,12 +108,11 @@ send(boost::shared_ptr<std::string const> const& ss)
// We are not currently writing, so send this immediately
ws_.async_write(
net::buffer(*queue_.front()),
net::bind_executor(strand_,
std::bind(
&websocket_session::on_write,
shared_from_this(),
std::placeholders::_1,
std::placeholders::_2)));
std::placeholders::_2));
}
void
@ -134,10 +130,9 @@ on_write(beast::error_code ec, std::size_t)
if(! queue_.empty())
ws_.async_write(
net::buffer(*queue_.front()),
net::bind_executor(strand_,
std::bind(
&websocket_session::on_write,
shared_from_this(),
std::placeholders::_1,
std::placeholders::_2)));
std::placeholders::_2));
}

View File

@ -27,10 +27,9 @@ class shared_state;
class websocket_session : public boost::enable_shared_from_this<websocket_session>
{
beast::flat_buffer buffer_;
websocket::stream<tcp::socket> ws_;
websocket::stream<beast::tcp_stream<net::io_context::strand>> ws_;
boost::shared_ptr<shared_state> state_;
std::vector<boost::shared_ptr<std::string const>> queue_;
net::strand<net::io_context::executor_type> strand_;
void fail(beast::error_code ec, char const* what);
void on_accept(beast::error_code ec);
@ -39,7 +38,7 @@ class websocket_session : public boost::enable_shared_from_this<websocket_sessio
public:
websocket_session(
tcp::socket socket,
tcp::socket&& socket,
boost::shared_ptr<shared_state> const& state);
~websocket_session();

View File

@ -18,9 +18,8 @@
#include <boost/beast/core.hpp>
#include <boost/beast/websocket.hpp>
#include <boost/beast/websocket/ssl.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/beast/_experimental/core/ssl_stream.hpp>
#include <boost/asio/spawn.hpp>
#include <boost/asio/ssl/stream.hpp>
#include <algorithm>
#include <cstdlib>
#include <functional>
@ -39,6 +38,11 @@ using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
//------------------------------------------------------------------------------
// The type of websocket stream to use
// Stackful coroutines are already stranded.
using ws_type = websocket::stream<beast::ssl_stream<
beast::tcp_stream<net::io_context::executor_type>>>;
// Report a failure
void
fail(beast::error_code ec, char const* what)
@ -49,14 +53,13 @@ fail(beast::error_code ec, char const* what)
// Echoes back all received WebSocket messages
void
do_session(
tcp::socket& socket,
ssl::context& ctx,
ws_type& ws,
net::yield_context yield)
{
beast::error_code ec;
// Construct the stream by moving in the socket
websocket::stream<ssl::stream<tcp::socket&>> ws{socket, ctx};
// Set the timeout.
beast::get_lowest_layer(ws).expires_after(std::chrono::seconds(30));
// Perform the SSL handshake
ws.next_layer().async_handshake(ssl::stream_base::server, yield[ec]);
@ -135,8 +138,7 @@ do_listen(
acceptor.get_executor().context(),
std::bind(
&do_session,
std::move(socket),
std::ref(ctx),
ws_type(std::move(socket), ctx),
std::placeholders::_1));
}
}

View File

@ -15,7 +15,6 @@
#include <boost/beast/core.hpp>
#include <boost/beast/websocket.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/spawn.hpp>
#include <algorithm>
#include <cstdlib>
@ -34,6 +33,11 @@ using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
//------------------------------------------------------------------------------
// The type of websocket stream to use
// Stackful coroutines are already stranded.
using ws_type = websocket::stream<
beast::tcp_stream<net::io_context::executor_type>>;
// Report a failure
void
fail(beast::error_code ec, char const* what)
@ -43,13 +47,10 @@ fail(beast::error_code ec, char const* what)
// Echoes back all received WebSocket messages
void
do_session(tcp::socket& socket, net::yield_context yield)
do_session(ws_type& ws, net::yield_context yield)
{
beast::error_code ec;
// Construct the stream by moving in the socket
websocket::stream<tcp::socket> ws{std::move(socket)};
// Accept the websocket handshake
ws.async_accept(yield[ec]);
if(ec)
@ -121,7 +122,7 @@ do_listen(
acceptor.get_executor().context(),
std::bind(
&do_session,
std::move(socket),
ws_type(std::move(socket)),
std::placeholders::_1));
}
}

View File

@ -30,10 +30,8 @@
#include <boost/beast/http.hpp>
#include <boost/beast/version.hpp>
#include <boost/beast/websocket.hpp>
#include <boost/asio/bind_executor.hpp>
#include <boost/asio/spawn.hpp>
#include <boost/asio/strand.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <algorithm>
#include <cstdlib>
#include <functional>
@ -80,12 +78,16 @@ setup_stream(websocket::stream<NextLayer>& ws)
//------------------------------------------------------------------------------
// The type of websocket stream to use
// Stackful coroutines are already stranded.
using ws_type = websocket::stream<
beast::tcp_stream<net::io_context::executor_type>>;
void
do_sync_session(tcp::socket& socket)
do_sync_session(ws_type& ws)
{
beast::error_code ec;
websocket::stream<tcp::socket> ws{std::move(socket)};
setup_stream(ws);
ws.accept_ex(
@ -131,7 +133,7 @@ do_sync_listen(
std::thread{std::bind(
&do_sync_session,
std::move(socket))}.detach();
ws_type(std::move(socket)))}.detach();
}
}
@ -140,9 +142,7 @@ do_sync_listen(
// Echoes back all received WebSocket messages
class async_session : public std::enable_shared_from_this<async_session>
{
websocket::stream<tcp::socket> ws_;
net::strand<
net::io_context::executor_type> strand_;
websocket::stream<beast::tcp_stream<net::io_context::strand>> ws_;
beast::multi_buffer buffer_;
public:
@ -150,7 +150,6 @@ public:
explicit
async_session(tcp::socket socket)
: ws_(std::move(socket))
, strand_(ws_.get_executor())
{
setup_stream(ws_);
}
@ -166,12 +165,10 @@ public:
res.set(http::field::server,
"Boost.Beast/" + std::to_string(BOOST_BEAST_VERSION) + "-Async");
},
net::bind_executor(
strand_,
std::bind(
&async_session::on_accept,
shared_from_this(),
std::placeholders::_1)));
std::placeholders::_1));
}
void
@ -190,13 +187,11 @@ public:
// Read a message into our buffer
ws_.async_read(
buffer_,
net::bind_executor(
strand_,
std::bind(
&async_session::on_read,
shared_from_this(),
std::placeholders::_1,
std::placeholders::_2)));
std::placeholders::_2));
}
void
@ -217,13 +212,11 @@ public:
ws_.text(ws_.got_text());
ws_.async_write(
buffer_.data(),
net::bind_executor(
strand_,
std::bind(
&async_session::on_write,
shared_from_this(),
std::placeholders::_1,
std::placeholders::_2)));
std::placeholders::_2));
}
void
@ -247,18 +240,13 @@ public:
// Accepts incoming connections and launches the sessions
class async_listener : public std::enable_shared_from_this<async_listener>
{
net::strand<
net::io_context::executor_type> strand_;
tcp::acceptor acceptor_;
tcp::socket socket_;
public:
async_listener(
net::io_context& ioc,
tcp::endpoint endpoint)
: strand_(ioc.get_executor())
, acceptor_(ioc)
, socket_(ioc)
: acceptor_(ioc)
{
beast::error_code ec;
@ -309,17 +297,15 @@ public:
do_accept()
{
acceptor_.async_accept(
socket_,
net::bind_executor(
strand_,
std::bind(
&async_listener::on_accept,
shared_from_this(),
std::placeholders::_1)));
std::placeholders::_1,
std::placeholders::_2));
}
void
on_accept(beast::error_code ec)
on_accept(beast::error_code ec, tcp::socket socket)
{
if(ec)
{
@ -328,7 +314,7 @@ public:
else
{
// Create the async_session and run it
std::make_shared<async_session>(std::move(socket_))->run();
std::make_shared<async_session>(std::move(socket))->run();
}
// Accept another connection
@ -339,11 +325,10 @@ public:
//------------------------------------------------------------------------------
void
do_coro_session(tcp::socket& socket, net::yield_context yield)
do_coro_session(ws_type& ws, net::yield_context yield)
{
beast::error_code ec;
websocket::stream<tcp::socket> ws{std::move(socket)};
setup_stream(ws);
ws.async_accept_ex(
@ -413,7 +398,7 @@ do_coro_listen(
acceptor.get_executor().context(),
std::bind(
&do_coro_session,
std::move(socket),
ws_type(std::move(socket)),
std::placeholders::_1));
}
}

View File

@ -18,10 +18,8 @@
#include <boost/beast/core.hpp>
#include <boost/beast/websocket.hpp>
#include <boost/beast/websocket/ssl.hpp>
#include <boost/asio/bind_executor.hpp>
#include <boost/beast/_experimental/core/ssl_stream.hpp>
#include <boost/asio/coroutine.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/ssl/stream.hpp>
#include <boost/asio/strand.hpp>
#include <algorithm>
#include <cstdlib>
@ -53,18 +51,14 @@ class session
: public net::coroutine
, public std::enable_shared_from_this<session>
{
tcp::socket socket_;
websocket::stream<ssl::stream<tcp::socket&>> ws_;
net::strand<
net::io_context::executor_type> strand_;
websocket::stream<beast::ssl_stream<
beast::tcp_stream<net::io_context::strand>>> ws_;
beast::multi_buffer buffer_;
public:
// Take ownership of the socket
session(tcp::socket socket, ssl::context& ctx)
: socket_(std::move(socket))
, ws_(socket_, ctx)
, strand_(ws_.get_executor())
session(tcp::socket&& socket, ssl::context& ctx)
: ws_(std::move(socket), ctx)
{
}
@ -88,25 +82,21 @@ public:
// Perform the SSL handshake
yield ws_.next_layer().async_handshake(
ssl::stream_base::server,
net::bind_executor(
strand_,
std::bind(
&session::loop,
shared_from_this(),
std::placeholders::_1,
0)));
0));
if(ec)
return fail(ec, "handshake");
// Accept the websocket handshake
yield ws_.async_accept(
net::bind_executor(
strand_,
std::bind(
&session::loop,
shared_from_this(),
std::placeholders::_1,
0)));
0));
if(ec)
return fail(ec, "accept");
@ -115,13 +105,11 @@ public:
// Read a message into our buffer
yield ws_.async_read(
buffer_,
net::bind_executor(
strand_,
std::bind(
&session::loop,
shared_from_this(),
std::placeholders::_1,
std::placeholders::_2)));
std::placeholders::_2));
if(ec == websocket::error::closed)
{
// This indicates that the session was closed
@ -134,13 +122,11 @@ public:
ws_.text(ws_.got_text());
yield ws_.async_write(
buffer_.data(),
net::bind_executor(
strand_,
std::bind(
&session::loop,
shared_from_this(),
std::placeholders::_1,
std::placeholders::_2)));
std::placeholders::_2));
if(ec)
return fail(ec, "write");

View File

@ -15,10 +15,8 @@
#include <boost/beast/core.hpp>
#include <boost/beast/websocket.hpp>
#include <boost/asio/bind_executor.hpp>
#include <boost/asio/coroutine.hpp>
#include <boost/asio/strand.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <algorithm>
#include <cstdlib>
#include <functional>
@ -48,9 +46,8 @@ class session
: public net::coroutine
, public std::enable_shared_from_this<session>
{
websocket::stream<tcp::socket> ws_;
net::strand<
net::io_context::executor_type> strand_;
websocket::stream<
beast::tcp_stream<net::io_context::strand>> ws_;
beast::multi_buffer buffer_;
public:
@ -58,7 +55,6 @@ public:
explicit
session(tcp::socket socket)
: ws_(std::move(socket))
, strand_(ws_.get_executor())
{
}
@ -80,13 +76,11 @@ public:
{
// Accept the websocket handshake
yield ws_.async_accept(
net::bind_executor(
strand_,
std::bind(
&session::loop,
shared_from_this(),
std::placeholders::_1,
0)));
0));
if(ec)
return fail(ec, "accept");
@ -95,13 +89,11 @@ public:
// Read a message into our buffer
yield ws_.async_read(
buffer_,
net::bind_executor(
strand_,
std::bind(
&session::loop,
shared_from_this(),
std::placeholders::_1,
std::placeholders::_2)));
std::placeholders::_2));
if(ec == websocket::error::closed)
{
// This indicates that the session was closed
@ -114,13 +106,11 @@ public:
ws_.text(ws_.got_text());
yield ws_.async_write(
buffer_.data(),
net::bind_executor(
strand_,
std::bind(
&session::loop,
shared_from_this(),
std::placeholders::_1,
std::placeholders::_2)));
std::placeholders::_2));
if(ec)
return fail(ec, "write");