mirror of
https://github.com/boostorg/beast.git
synced 2025-07-29 20:37:31 +02:00
Fixes to support Asio changes (API Change):
This adjusts Beast's interfaces and implementation to match the changes in Boost.Asio.
This commit is contained in:
@ -84,6 +84,11 @@ add_definitions (-DBOOST_ASIO_DISABLE_BOOST_ARRAY=1)
|
||||
add_definitions (-DBOOST_ASIO_DISABLE_BOOST_BIND=1)
|
||||
add_definitions (-DBOOST_ASIO_DISABLE_BOOST_DATE_TIME=1)
|
||||
add_definitions (-DBOOST_ASIO_DISABLE_BOOST_REGEX=1)
|
||||
|
||||
# workaround for asio defect
|
||||
add_definitions (-DBOOST_ASIO_DISABLE_WINDOWS_RANDOM_ACCESS_HANDLE=1)
|
||||
add_definitions (-DBOOST_ASIO_DISABLE_WINDOWS_STREAM_HANDLE=1)
|
||||
|
||||
add_definitions (-DBOOST_COROUTINES_NO_DEPRECATION_WARNING=1)
|
||||
|
||||
include_directories (${BOOST_ROOT})
|
||||
@ -174,6 +179,9 @@ endif()
|
||||
|
||||
include_directories (.)
|
||||
|
||||
# VFALCO FIXME Need this for recent asio changes
|
||||
add_definitions (-DBOOST_BEAST_NO_FILE_BODY_WIN32=1)
|
||||
|
||||
if (OPENSSL_FOUND)
|
||||
include_directories (${OPENSSL_INCLUDE_DIR})
|
||||
endif()
|
||||
|
8
Jamfile
8
Jamfile
@ -93,6 +93,14 @@ project /boost/beast
|
||||
<define>BOOST_ASIO_DISABLE_BOOST_DATE_TIME=1
|
||||
<define>BOOST_ASIO_DISABLE_BOOST_REGEX=1
|
||||
<define>BOOST_COROUTINES_NO_DEPRECATION_WARNING=1
|
||||
|
||||
# workaround for asio defect
|
||||
<define>BOOST_ASIO_DISABLE_WINDOWS_RANDOM_ACCESS_HANDLE=1
|
||||
<define>BOOST_ASIO_DISABLE_WINDOWS_STREAM_HANDLE=1
|
||||
|
||||
# VFALCO FIXME Need this for recent asio changes
|
||||
<define>BOOST_BEAST_NO_FILE_BODY_WIN32=1
|
||||
|
||||
<toolset>msvc:<cxxflags>"/bigobj"
|
||||
<toolset>msvc-14.1:<cxxflags>"/permissive-"
|
||||
<toolset>msvc:<define>_SCL_SECURE_NO_WARNINGS=1
|
||||
|
@ -331,27 +331,26 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Handles a plain WebSocket connection
|
||||
class plain_websocket_session
|
||||
: public websocket_session<plain_websocket_session>
|
||||
, public std::enable_shared_from_this<plain_websocket_session>
|
||||
{
|
||||
websocket::stream<
|
||||
beast::tcp_stream<net::io_context::strand>> ws_;
|
||||
bool close_ = false;
|
||||
websocket::stream<beast::tcp_stream> ws_;
|
||||
|
||||
public:
|
||||
// Create the session
|
||||
explicit
|
||||
plain_websocket_session(
|
||||
beast::tcp_stream<net::io_context::strand>&& stream)
|
||||
beast::tcp_stream&& stream)
|
||||
: ws_(std::move(stream))
|
||||
{
|
||||
}
|
||||
|
||||
// Called by the base class
|
||||
websocket::stream<
|
||||
beast::tcp_stream<net::io_context::strand>>&
|
||||
websocket::stream<beast::tcp_stream>&
|
||||
ws()
|
||||
{
|
||||
return ws_;
|
||||
@ -365,48 +364,28 @@ public:
|
||||
// Accept the WebSocket upgrade request
|
||||
do_accept(std::move(req));
|
||||
}
|
||||
|
||||
void
|
||||
on_close(beast::error_code ec)
|
||||
{
|
||||
// Happens when close times out
|
||||
if(ec == net::error::operation_aborted)
|
||||
return;
|
||||
|
||||
if(ec)
|
||||
return fail(ec, "close");
|
||||
|
||||
// At this point the connection is gracefully closed
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Handles an SSL WebSocket connection
|
||||
class ssl_websocket_session
|
||||
: public websocket_session<ssl_websocket_session>
|
||||
, public std::enable_shared_from_this<ssl_websocket_session>
|
||||
{
|
||||
websocket::stream<beast::ssl_stream<
|
||||
beast::tcp_stream<net::io_context::strand>>> ws_;
|
||||
bool eof_ = false;
|
||||
websocket::stream<
|
||||
beast::ssl_stream<beast::tcp_stream>> ws_;
|
||||
|
||||
public:
|
||||
// Create the http_session
|
||||
// Create the ssl_websocket_session
|
||||
explicit
|
||||
ssl_websocket_session(beast::ssl_stream<
|
||||
beast::tcp_stream<net::io_context::strand>>&& stream)
|
||||
ssl_websocket_session(
|
||||
beast::ssl_stream<beast::tcp_stream>&& stream)
|
||||
: ws_(std::move(stream))
|
||||
{
|
||||
}
|
||||
|
||||
// Called by the base class
|
||||
websocket::stream<beast::ssl_stream<
|
||||
beast::tcp_stream<net::io_context::strand>>>&
|
||||
ws()
|
||||
{
|
||||
return ws_;
|
||||
}
|
||||
|
||||
// Start the asynchronous operation
|
||||
// Start the session
|
||||
template<class Body, class Allocator>
|
||||
void
|
||||
run(http::request<Body, http::basic_fields<Allocator>> req)
|
||||
@ -415,18 +394,15 @@ public:
|
||||
do_accept(std::move(req));
|
||||
}
|
||||
|
||||
void
|
||||
do_eof()
|
||||
// Called by the base class
|
||||
websocket::stream<
|
||||
beast::ssl_stream<beast::tcp_stream>>&
|
||||
ws()
|
||||
{
|
||||
eof_ = true;
|
||||
|
||||
// Perform the SSL shutdown
|
||||
ws_.next_layer().async_shutdown(
|
||||
beast::bind_front_handler(
|
||||
&ssl_websocket_session::on_shutdown,
|
||||
shared_from_this()));
|
||||
return ws_;
|
||||
}
|
||||
|
||||
private:
|
||||
void
|
||||
on_shutdown(beast::error_code ec)
|
||||
{
|
||||
@ -437,10 +413,12 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<class Body, class Allocator>
|
||||
void
|
||||
make_websocket_session(
|
||||
beast::tcp_stream<net::io_context::strand> stream,
|
||||
beast::tcp_stream stream,
|
||||
http::request<Body, http::basic_fields<Allocator>> req)
|
||||
{
|
||||
std::make_shared<plain_websocket_session>(
|
||||
@ -450,7 +428,7 @@ make_websocket_session(
|
||||
template<class Body, class Allocator>
|
||||
void
|
||||
make_websocket_session(
|
||||
beast::ssl_stream<beast::tcp_stream<net::io_context::strand>> stream,
|
||||
beast::ssl_stream<beast::tcp_stream> stream,
|
||||
http::request<Body, http::basic_fields<Allocator>> req)
|
||||
{
|
||||
std::make_shared<ssl_websocket_session>(
|
||||
@ -568,19 +546,15 @@ class http_session
|
||||
queue queue_;
|
||||
|
||||
protected:
|
||||
net::steady_timer timer_;
|
||||
beast::flat_buffer buffer_;
|
||||
|
||||
public:
|
||||
// Construct the session
|
||||
http_session(
|
||||
net::io_context& ioc,
|
||||
beast::flat_buffer buffer,
|
||||
std::shared_ptr<std::string const> const& doc_root)
|
||||
: doc_root_(doc_root)
|
||||
, queue_(*this)
|
||||
, timer_(ioc,
|
||||
(std::chrono::steady_clock::time_point::max)())
|
||||
, buffer_(std::move(buffer))
|
||||
{
|
||||
}
|
||||
@ -621,7 +595,11 @@ public:
|
||||
// See if it is a WebSocket Upgrade
|
||||
if(websocket::is_upgrade(req_))
|
||||
{
|
||||
// Transfer the stream to a new WebSocket session
|
||||
// Disable the timeout.
|
||||
// The websocket::stream uses its own timeout settings.
|
||||
beast::get_lowest_layer(derived().stream()).expires_never();
|
||||
|
||||
// Transfer the stream to a new WebSocket session.
|
||||
return make_websocket_session(
|
||||
derived().release_stream(),
|
||||
std::move(req_));
|
||||
@ -663,56 +641,50 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Handles a plain HTTP connection
|
||||
class plain_http_session
|
||||
: public http_session<plain_http_session>
|
||||
, public std::enable_shared_from_this<plain_http_session>
|
||||
{
|
||||
beast::tcp_stream<net::io_context::strand> stream_;
|
||||
beast::tcp_stream stream_;
|
||||
|
||||
public:
|
||||
// Create the http_session
|
||||
// Create the session
|
||||
plain_http_session(
|
||||
beast::tcp_stream<net::io_context::strand>&& stream,
|
||||
beast::tcp_stream&& stream,
|
||||
beast::flat_buffer&& buffer,
|
||||
std::shared_ptr<std::string const> const& doc_root)
|
||||
: http_session<plain_http_session>(
|
||||
stream.get_executor().context(),
|
||||
std::move(buffer),
|
||||
doc_root)
|
||||
, stream_(std::move(stream))
|
||||
{
|
||||
}
|
||||
|
||||
// Start the session
|
||||
void
|
||||
run()
|
||||
{
|
||||
this->do_read();
|
||||
}
|
||||
|
||||
// Called by the base class
|
||||
beast::tcp_stream<net::io_context::strand>&
|
||||
beast::tcp_stream&
|
||||
stream()
|
||||
{
|
||||
return stream_;
|
||||
}
|
||||
|
||||
// Called by the base class
|
||||
beast::tcp_stream<net::io_context::strand>
|
||||
beast::tcp_stream
|
||||
release_stream()
|
||||
{
|
||||
return std::move(stream_);
|
||||
}
|
||||
|
||||
// Start the asynchronous operation
|
||||
void
|
||||
run()
|
||||
{
|
||||
// Make sure we run on the strand
|
||||
if(! stream_.get_executor().running_in_this_thread())
|
||||
return net::post(
|
||||
stream_.get_executor(),
|
||||
beast::bind_front_handler(
|
||||
&plain_http_session::run,
|
||||
shared_from_this()));
|
||||
|
||||
do_read();
|
||||
}
|
||||
|
||||
// Called by the base class
|
||||
void
|
||||
do_eof()
|
||||
{
|
||||
@ -722,70 +694,35 @@ public:
|
||||
|
||||
// At this point the connection is closed gracefully
|
||||
}
|
||||
|
||||
void
|
||||
do_timeout()
|
||||
{
|
||||
// Closing the socket cancels all outstanding operations. They
|
||||
// will complete with net::error::operation_aborted
|
||||
beast::error_code ec;
|
||||
stream_.socket().shutdown(tcp::socket::shutdown_both, ec);
|
||||
stream_.socket().close(ec);
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Handles an SSL HTTP connection
|
||||
class ssl_http_session
|
||||
: public http_session<ssl_http_session>
|
||||
, public std::enable_shared_from_this<ssl_http_session>
|
||||
{
|
||||
beast::ssl_stream<
|
||||
beast::tcp_stream<net::io_context::strand>> stream_;
|
||||
bool eof_ = false;
|
||||
beast::ssl_stream<beast::tcp_stream> stream_;
|
||||
|
||||
public:
|
||||
// Create the http_session
|
||||
ssl_http_session(
|
||||
beast::tcp_stream<net::io_context::strand>&& stream,
|
||||
beast::tcp_stream&& stream,
|
||||
ssl::context& ctx,
|
||||
beast::flat_buffer&& buffer,
|
||||
std::shared_ptr<std::string const> const& doc_root)
|
||||
: http_session<ssl_http_session>(
|
||||
stream.get_executor().context(),
|
||||
std::move(buffer),
|
||||
doc_root)
|
||||
, stream_(std::move(stream), ctx)
|
||||
{
|
||||
}
|
||||
|
||||
// Called by the base class
|
||||
beast::ssl_stream<
|
||||
beast::tcp_stream<net::io_context::strand>>&
|
||||
stream()
|
||||
{
|
||||
return stream_;
|
||||
}
|
||||
|
||||
// Called by the base class
|
||||
beast::ssl_stream<
|
||||
beast::tcp_stream<net::io_context::strand>>
|
||||
release_stream()
|
||||
{
|
||||
return std::move(stream_);
|
||||
}
|
||||
|
||||
// Start the asynchronous operation
|
||||
// Start the session
|
||||
void
|
||||
run()
|
||||
{
|
||||
// Make sure we run on the strand
|
||||
if(! stream_.get_executor().running_in_this_thread())
|
||||
return net::post(
|
||||
stream_.get_executor(),
|
||||
beast::bind_front_handler(
|
||||
&ssl_http_session::run,
|
||||
shared_from_this()));
|
||||
|
||||
// Set the timeout.
|
||||
beast::get_lowest_layer(stream_).expires_after(std::chrono::seconds(30));
|
||||
|
||||
@ -798,6 +735,36 @@ public:
|
||||
&ssl_http_session::on_handshake,
|
||||
shared_from_this()));
|
||||
}
|
||||
|
||||
// Called by the base class
|
||||
beast::ssl_stream<beast::tcp_stream>&
|
||||
stream()
|
||||
{
|
||||
return stream_;
|
||||
}
|
||||
|
||||
// Called by the base class
|
||||
beast::ssl_stream<beast::tcp_stream>
|
||||
release_stream()
|
||||
{
|
||||
return std::move(stream_);
|
||||
}
|
||||
|
||||
// Called by the base class
|
||||
void
|
||||
do_eof()
|
||||
{
|
||||
// Set the timeout.
|
||||
beast::get_lowest_layer(stream_).expires_after(std::chrono::seconds(30));
|
||||
|
||||
// Perform the SSL shutdown
|
||||
stream_.async_shutdown(
|
||||
beast::bind_front_handler(
|
||||
&ssl_http_session::on_shutdown,
|
||||
shared_from_this()));
|
||||
}
|
||||
|
||||
private:
|
||||
void
|
||||
on_handshake(
|
||||
beast::error_code ec,
|
||||
@ -812,21 +779,6 @@ public:
|
||||
do_read();
|
||||
}
|
||||
|
||||
void
|
||||
do_eof()
|
||||
{
|
||||
eof_ = true;
|
||||
|
||||
// Set the timeout.
|
||||
beast::get_lowest_layer(stream_).expires_after(std::chrono::seconds(30));
|
||||
|
||||
// Perform the SSL shutdown
|
||||
stream_.async_shutdown(
|
||||
beast::bind_front_handler(
|
||||
&ssl_http_session::on_shutdown,
|
||||
shared_from_this()));
|
||||
}
|
||||
|
||||
void
|
||||
on_shutdown(beast::error_code ec)
|
||||
{
|
||||
@ -846,7 +798,7 @@ public:
|
||||
// Detects SSL handshakes
|
||||
class detect_session : public std::enable_shared_from_this<detect_session>
|
||||
{
|
||||
beast::tcp_stream<net::io_context::strand> stream_;
|
||||
beast::tcp_stream stream_;
|
||||
ssl::context& ctx_;
|
||||
std::shared_ptr<std::string const> doc_root_;
|
||||
beast::flat_buffer buffer_;
|
||||
@ -854,7 +806,7 @@ class detect_session : public std::enable_shared_from_this<detect_session>
|
||||
public:
|
||||
explicit
|
||||
detect_session(
|
||||
tcp::socket socket,
|
||||
tcp::socket&& socket,
|
||||
ssl::context& ctx,
|
||||
std::shared_ptr<std::string const> const& doc_root)
|
||||
: stream_(std::move(socket))
|
||||
@ -906,8 +858,10 @@ public:
|
||||
// Accepts incoming connections and launches the sessions
|
||||
class listener : public std::enable_shared_from_this<listener>
|
||||
{
|
||||
net::io_context& ioc_;
|
||||
ssl::context& ctx_;
|
||||
tcp::acceptor acceptor_;
|
||||
tcp::socket socket_;
|
||||
std::shared_ptr<std::string const> doc_root_;
|
||||
|
||||
public:
|
||||
@ -916,8 +870,10 @@ public:
|
||||
ssl::context& ctx,
|
||||
tcp::endpoint endpoint,
|
||||
std::shared_ptr<std::string const> const& doc_root)
|
||||
: ctx_(ctx)
|
||||
, acceptor_(ioc)
|
||||
: ioc_(ioc)
|
||||
, ctx_(ctx)
|
||||
, acceptor_(beast::make_strand(ioc))
|
||||
, socket_(beast::make_strand(ioc))
|
||||
, doc_root_(doc_root)
|
||||
{
|
||||
beast::error_code ec;
|
||||
@ -969,13 +925,14 @@ public:
|
||||
do_accept()
|
||||
{
|
||||
acceptor_.async_accept(
|
||||
socket_,
|
||||
beast::bind_front_handler(
|
||||
&listener::on_accept,
|
||||
shared_from_this()));
|
||||
}
|
||||
|
||||
void
|
||||
on_accept(beast::error_code ec, tcp::socket socket)
|
||||
on_accept(beast::error_code ec)
|
||||
{
|
||||
if(ec)
|
||||
{
|
||||
@ -985,11 +942,14 @@ public:
|
||||
{
|
||||
// Create the detector http_session and run it
|
||||
std::make_shared<detect_session>(
|
||||
std::move(socket),
|
||||
std::move(socket_),
|
||||
ctx_,
|
||||
doc_root_)->run();
|
||||
}
|
||||
|
||||
// Make sure each session gets its own strand
|
||||
socket_ = tcp::socket(beast::make_strand(ioc_));
|
||||
|
||||
// Accept another connection
|
||||
do_accept();
|
||||
}
|
||||
|
@ -219,14 +219,13 @@ fail(beast::error_code ec, char const* what)
|
||||
// Echoes back all received WebSocket messages
|
||||
class websocket_session : public std::enable_shared_from_this<websocket_session>
|
||||
{
|
||||
websocket::stream<beast::tcp_stream<net::io_context::strand>> ws_;
|
||||
websocket::stream<beast::tcp_stream> ws_;
|
||||
beast::flat_buffer buffer_;
|
||||
char ping_state_ = 0;
|
||||
|
||||
public:
|
||||
// Take ownership of the socket
|
||||
explicit
|
||||
websocket_session(tcp::socket socket)
|
||||
websocket_session(tcp::socket&& socket)
|
||||
: ws_(std::move(socket))
|
||||
{
|
||||
}
|
||||
@ -258,6 +257,7 @@ public:
|
||||
shared_from_this()));
|
||||
}
|
||||
|
||||
private:
|
||||
void
|
||||
on_accept(beast::error_code ec)
|
||||
{
|
||||
@ -413,7 +413,7 @@ class http_session : public std::enable_shared_from_this<http_session>
|
||||
}
|
||||
};
|
||||
|
||||
beast::tcp_stream<net::io_context::strand> stream_;
|
||||
beast::tcp_stream stream_;
|
||||
beast::flat_buffer buffer_;
|
||||
std::shared_ptr<std::string const> doc_root_;
|
||||
http::request<http::string_body> req_;
|
||||
@ -421,9 +421,8 @@ class http_session : public std::enable_shared_from_this<http_session>
|
||||
|
||||
public:
|
||||
// Take ownership of the socket
|
||||
explicit
|
||||
http_session(
|
||||
tcp::socket socket,
|
||||
tcp::socket&& socket,
|
||||
std::shared_ptr<std::string const> const& doc_root)
|
||||
: stream_(std::move(socket))
|
||||
, doc_root_(doc_root)
|
||||
@ -431,21 +430,14 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
// Start the asynchronous operation
|
||||
// Start the session
|
||||
void
|
||||
run()
|
||||
{
|
||||
// Make sure we run on the strand
|
||||
if(! stream_.get_executor().running_in_this_thread())
|
||||
return net::post(
|
||||
stream_.get_executor(),
|
||||
std::bind(
|
||||
&http_session::run,
|
||||
shared_from_this()));
|
||||
|
||||
do_read();
|
||||
}
|
||||
|
||||
private:
|
||||
void
|
||||
do_read()
|
||||
{
|
||||
@ -532,6 +524,7 @@ public:
|
||||
// Accepts incoming connections and launches the sessions
|
||||
class listener : public std::enable_shared_from_this<listener>
|
||||
{
|
||||
net::io_context& ioc_;
|
||||
tcp::acceptor acceptor_;
|
||||
tcp::socket socket_;
|
||||
std::shared_ptr<std::string const> doc_root_;
|
||||
@ -541,8 +534,9 @@ public:
|
||||
net::io_context& ioc,
|
||||
tcp::endpoint endpoint,
|
||||
std::shared_ptr<std::string const> const& doc_root)
|
||||
: acceptor_(ioc)
|
||||
, socket_(ioc)
|
||||
: ioc_(ioc)
|
||||
, acceptor_(beast::make_strand(ioc))
|
||||
, socket_(beast::make_strand(ioc))
|
||||
, doc_root_(doc_root)
|
||||
{
|
||||
beast::error_code ec;
|
||||
@ -594,13 +588,14 @@ public:
|
||||
do_accept()
|
||||
{
|
||||
acceptor_.async_accept(
|
||||
socket_,
|
||||
beast::bind_front_handler(
|
||||
&listener::on_accept,
|
||||
shared_from_this()));
|
||||
}
|
||||
|
||||
void
|
||||
on_accept(beast::error_code ec, tcp::socket socket)
|
||||
on_accept(beast::error_code ec)
|
||||
{
|
||||
if(ec)
|
||||
{
|
||||
@ -610,10 +605,13 @@ public:
|
||||
{
|
||||
// Create the http session and run it
|
||||
std::make_shared<http_session>(
|
||||
std::move(socket),
|
||||
std::move(socket_),
|
||||
doc_root_)->run();
|
||||
}
|
||||
|
||||
// Make sure each session gets its own strand
|
||||
socket_ = tcp::socket(beast::make_strand(ioc_));
|
||||
|
||||
// Accept another connection
|
||||
do_accept();
|
||||
}
|
||||
|
@ -33,10 +33,6 @@ using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// The type of stream to use
|
||||
using stream_type =
|
||||
beast::ssl_stream<beast::tcp_stream<net::io_context::executor_type>>;
|
||||
|
||||
// Report a failure
|
||||
void
|
||||
fail(beast::error_code ec, char const* what)
|
||||
@ -48,17 +44,18 @@ fail(beast::error_code ec, char const* what)
|
||||
class session : public std::enable_shared_from_this<session>
|
||||
{
|
||||
tcp::resolver resolver_;
|
||||
stream_type stream_;
|
||||
beast::ssl_stream<beast::tcp_stream> stream_;
|
||||
beast::flat_buffer buffer_; // (Must persist between reads)
|
||||
http::request<http::empty_body> req_;
|
||||
http::response<http::string_body> res_;
|
||||
|
||||
public:
|
||||
// Resolver and stream require an io_context
|
||||
// Objects are constructed with a strand to
|
||||
// ensure that handlers do not execute concurrently.
|
||||
explicit
|
||||
session(net::io_context& ioc, ssl::context& ctx)
|
||||
: resolver_(ioc)
|
||||
, stream_(ioc, ctx)
|
||||
: resolver_(beast::make_strand(ioc))
|
||||
, stream_(beast::make_strand(ioc), ctx)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -29,9 +29,6 @@ using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// The type of stream to use
|
||||
using stream_type = beast::tcp_stream<net::io_context::executor_type>;
|
||||
|
||||
// Report a failure
|
||||
void
|
||||
fail(beast::error_code ec, char const* what)
|
||||
@ -43,17 +40,18 @@ fail(beast::error_code ec, char const* what)
|
||||
class session : public std::enable_shared_from_this<session>
|
||||
{
|
||||
tcp::resolver resolver_;
|
||||
stream_type stream_;
|
||||
beast::tcp_stream stream_;
|
||||
beast::flat_buffer buffer_; // (Must persist between reads)
|
||||
http::request<http::empty_body> req_;
|
||||
http::response<http::string_body> res_;
|
||||
|
||||
public:
|
||||
// Resolver and socket require an io_context
|
||||
// Objects are constructed with a strand to
|
||||
// ensure that handlers do not execute concurrently.
|
||||
explicit
|
||||
session(net::io_context& ioc)
|
||||
: resolver_(ioc)
|
||||
, stream_(ioc)
|
||||
: resolver_(beast::make_strand(ioc))
|
||||
, stream_(beast::make_strand(ioc))
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -33,11 +33,6 @@ using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// The type of stream to use
|
||||
// Stackful coroutines are already stranded.
|
||||
using stream_type =
|
||||
beast::ssl_stream<beast::tcp_stream<net::io_context::executor_type>>;
|
||||
|
||||
// Report a failure
|
||||
void
|
||||
fail(beast::error_code ec, char const* what)
|
||||
@ -60,7 +55,7 @@ do_session(
|
||||
|
||||
// These objects perform our I/O
|
||||
tcp::resolver resolver(ioc);
|
||||
stream_type stream(ioc, ctx);
|
||||
beast::ssl_stream<beast::tcp_stream> stream(ioc, ctx);
|
||||
|
||||
// Set SNI Hostname (many hosts need this to handshake successfully)
|
||||
if(! SSL_set_tlsext_host_name(stream.native_handle(), host.c_str()))
|
||||
|
@ -29,10 +29,6 @@ using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// The type of stream to use.
|
||||
// Stackful coroutines are already stranded.
|
||||
using stream_type = beast::tcp_stream<net::io_context::executor_type>;
|
||||
|
||||
// Report a failure
|
||||
void
|
||||
fail(beast::error_code ec, char const* what)
|
||||
@ -53,8 +49,8 @@ do_session(
|
||||
beast::error_code ec;
|
||||
|
||||
// These objects perform our I/O
|
||||
tcp::resolver resolver{ioc};
|
||||
stream_type stream(ioc);
|
||||
tcp::resolver resolver(ioc);
|
||||
beast::tcp_stream stream(ioc);
|
||||
|
||||
// Look up the domain name
|
||||
auto const results = resolver.async_resolve(host, port, yield[ec]);
|
||||
|
@ -151,10 +151,7 @@ class worker : public std::enable_shared_from_this<worker>
|
||||
|
||||
crawl_report& report_;
|
||||
tcp::resolver resolver_;
|
||||
tcp::socket socket_;
|
||||
net::steady_timer timer_;
|
||||
net::strand<
|
||||
net::io_context::executor_type> strand_;
|
||||
beast::tcp_stream stream_;
|
||||
beast::flat_buffer buffer_; // (Must persist between reads)
|
||||
http::request<http::empty_body> req_;
|
||||
http::response<http::string_body> res_;
|
||||
@ -167,11 +164,8 @@ public:
|
||||
crawl_report& report,
|
||||
net::io_context& ioc)
|
||||
: report_(report)
|
||||
, resolver_(ioc)
|
||||
, socket_(ioc)
|
||||
, timer_(ioc,
|
||||
(chrono::steady_clock::time_point::max)())
|
||||
, strand_(ioc.get_executor())
|
||||
, resolver_(beast::make_strand(ioc))
|
||||
, stream_(beast::make_strand(ioc))
|
||||
{
|
||||
// Set up the common fields of the request
|
||||
req_.version(11);
|
||||
@ -184,44 +178,9 @@ public:
|
||||
void
|
||||
run()
|
||||
{
|
||||
// Run the timer. The timer is operated
|
||||
// continuously, this simplifies the code.
|
||||
on_timer({});
|
||||
|
||||
do_get_host();
|
||||
}
|
||||
|
||||
void
|
||||
on_timer(beast::error_code ec)
|
||||
{
|
||||
if(ec && ec != net::error::operation_aborted)
|
||||
{
|
||||
// Should never happen
|
||||
report_.aggregate(
|
||||
[](crawl_report& rep)
|
||||
{
|
||||
++rep.timer_failures;
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Verify that the timer really expired since the deadline may have moved.
|
||||
if(timer_.expiry() <= chrono::steady_clock::now())
|
||||
{
|
||||
socket_.shutdown(tcp::socket::shutdown_both, ec);
|
||||
socket_.close(ec);
|
||||
return;
|
||||
}
|
||||
|
||||
// Wait on the timer
|
||||
timer_.async_wait(
|
||||
net::bind_executor(
|
||||
strand_,
|
||||
beast::bind_front_handler(
|
||||
&worker::on_timer,
|
||||
shared_from_this())));
|
||||
}
|
||||
|
||||
void
|
||||
do_get_host()
|
||||
{
|
||||
@ -230,27 +189,19 @@ public:
|
||||
|
||||
// nullptr means no more work
|
||||
if(! host)
|
||||
{
|
||||
timer_.cancel_one();
|
||||
return;
|
||||
}
|
||||
|
||||
// The Host HTTP field is required
|
||||
req_.set(http::field::host, host);
|
||||
|
||||
// Set the timer
|
||||
timer_.expires_after(chrono::seconds(timeout));
|
||||
|
||||
// Set up an HTTP GET request message
|
||||
// Look up the domain name
|
||||
resolver_.async_resolve(
|
||||
host,
|
||||
"http",
|
||||
net::bind_executor(
|
||||
strand_,
|
||||
beast::bind_front_handler(
|
||||
&worker::on_resolve,
|
||||
shared_from_this())));
|
||||
beast::bind_front_handler(
|
||||
&worker::on_resolve,
|
||||
shared_from_this()));
|
||||
}
|
||||
|
||||
void
|
||||
@ -268,18 +219,16 @@ public:
|
||||
return do_get_host();
|
||||
}
|
||||
|
||||
// Set the timer
|
||||
timer_.expires_after(chrono::seconds(timeout));
|
||||
// Set a timeout on the operation
|
||||
stream_.expires_after(std::chrono::seconds(10));
|
||||
|
||||
// Make the connection on the IP address we get from a lookup
|
||||
net::async_connect(
|
||||
socket_,
|
||||
beast::async_connect(
|
||||
stream_,
|
||||
results,
|
||||
net::bind_executor(
|
||||
strand_,
|
||||
beast::bind_front_handler(
|
||||
&worker::on_connect,
|
||||
shared_from_this())));
|
||||
beast::bind_front_handler(
|
||||
&worker::on_connect,
|
||||
shared_from_this()));
|
||||
}
|
||||
|
||||
void
|
||||
@ -295,18 +244,16 @@ public:
|
||||
return do_get_host();
|
||||
}
|
||||
|
||||
// Set the timer
|
||||
timer_.expires_after(chrono::seconds(timeout));
|
||||
// Set a timeout on the operation
|
||||
stream_.expires_after(std::chrono::seconds(10));
|
||||
|
||||
// Send the HTTP request to the remote host
|
||||
http::async_write(
|
||||
socket_,
|
||||
stream_,
|
||||
req_,
|
||||
net::bind_executor(
|
||||
strand_,
|
||||
beast::bind_front_handler(
|
||||
&worker::on_write,
|
||||
shared_from_this())));
|
||||
beast::bind_front_handler(
|
||||
&worker::on_write,
|
||||
shared_from_this()));
|
||||
}
|
||||
|
||||
void
|
||||
@ -325,21 +272,16 @@ public:
|
||||
});
|
||||
return do_get_host();
|
||||
}
|
||||
|
||||
// Set the timer
|
||||
timer_.expires_after(chrono::seconds(timeout));
|
||||
|
||||
// Receive the HTTP response
|
||||
res_ = {};
|
||||
http::async_read(
|
||||
socket_,
|
||||
stream_,
|
||||
buffer_,
|
||||
res_,
|
||||
net::bind_executor(
|
||||
strand_,
|
||||
beast::bind_front_handler(
|
||||
&worker::on_read,
|
||||
shared_from_this())));
|
||||
beast::bind_front_handler(
|
||||
&worker::on_read,
|
||||
shared_from_this()));
|
||||
}
|
||||
|
||||
void
|
||||
@ -368,8 +310,8 @@ public:
|
||||
});
|
||||
|
||||
// Gracefully close the socket
|
||||
socket_.shutdown(tcp::socket::shutdown_both, ec);
|
||||
socket_.close(ec);
|
||||
stream_.socket().shutdown(tcp::socket::shutdown_both, ec);
|
||||
stream_.close();
|
||||
|
||||
// If we get here then the connection is closed gracefully
|
||||
|
||||
@ -412,7 +354,7 @@ int main(int argc, char* argv[])
|
||||
auto const threads = std::max<int>(1, std::atoi(argv[1]));
|
||||
|
||||
// The io_context is required for all I/O
|
||||
net::io_context ioc{1};
|
||||
net::io_context ioc;
|
||||
|
||||
// The work keeps io_context::run from returning
|
||||
auto work = net::make_work_guard(ioc);
|
||||
|
@ -57,7 +57,7 @@ int main(int argc, char** argv)
|
||||
net::io_context ioc;
|
||||
|
||||
// The SSL context is required, and holds certificates
|
||||
ssl::context ctx{ssl::context::sslv23_client};
|
||||
ssl::context ctx(ssl::context::sslv23_client);
|
||||
|
||||
// This holds the root certificate used for verification
|
||||
load_root_certificates(ctx);
|
||||
@ -66,8 +66,8 @@ int main(int argc, char** argv)
|
||||
ctx.set_verify_mode(ssl::verify_peer);
|
||||
|
||||
// These objects perform our I/O
|
||||
tcp::resolver resolver{ioc};
|
||||
beast::ssl_stream<tcp::socket> stream{ioc, ctx};
|
||||
tcp::resolver resolver(ioc);
|
||||
beast::ssl_stream<beast::tcp_stream> stream(ioc, ctx);
|
||||
|
||||
// Set SNI Hostname (many hosts need this to handshake successfully)
|
||||
if(! SSL_set_tlsext_host_name(stream.native_handle(), host))
|
||||
@ -80,7 +80,7 @@ int main(int argc, char** argv)
|
||||
auto const results = resolver.resolve(host, port);
|
||||
|
||||
// Make the connection on the IP address we get from a lookup
|
||||
net::connect(stream.next_layer(), results.begin(), results.end());
|
||||
beast::connect(beast::get_lowest_layer(stream), results);
|
||||
|
||||
// Perform the SSL handshake
|
||||
stream.handshake(ssl::stream_base::client);
|
||||
|
@ -53,14 +53,14 @@ int main(int argc, char** argv)
|
||||
net::io_context ioc;
|
||||
|
||||
// These objects perform our I/O
|
||||
tcp::resolver resolver{ioc};
|
||||
tcp::socket socket{ioc};
|
||||
tcp::resolver resolver(ioc);
|
||||
beast::tcp_stream stream(ioc);
|
||||
|
||||
// Look up the domain name
|
||||
auto const results = resolver.resolve(host, port);
|
||||
|
||||
// Make the connection on the IP address we get from a lookup
|
||||
net::connect(socket, results.begin(), results.end());
|
||||
beast::connect(stream, results);
|
||||
|
||||
// Set up an HTTP GET request message
|
||||
http::request<http::string_body> req{http::verb::get, target, version};
|
||||
@ -68,7 +68,7 @@ int main(int argc, char** argv)
|
||||
req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);
|
||||
|
||||
// Send the HTTP request to the remote host
|
||||
http::write(socket, req);
|
||||
http::write(stream, req);
|
||||
|
||||
// This buffer is used for reading and must be persisted
|
||||
beast::flat_buffer buffer;
|
||||
@ -77,14 +77,14 @@ int main(int argc, char** argv)
|
||||
http::response<http::dynamic_body> res;
|
||||
|
||||
// Receive the HTTP response
|
||||
http::read(socket, buffer, res);
|
||||
http::read(stream, buffer, res);
|
||||
|
||||
// Write the message to standard out
|
||||
std::cout << res << std::endl;
|
||||
|
||||
// Gracefully close the socket
|
||||
beast::error_code ec;
|
||||
socket.shutdown(tcp::socket::shutdown_both, ec);
|
||||
stream.socket().shutdown(tcp::socket::shutdown_both, ec);
|
||||
|
||||
// not_connected happens sometimes
|
||||
// so don't bother reporting it.
|
||||
|
@ -255,7 +255,7 @@ class session : public std::enable_shared_from_this<session>
|
||||
}
|
||||
};
|
||||
|
||||
beast::ssl_stream<beast::tcp_stream<net::io_context::strand>> stream_;
|
||||
beast::ssl_stream<beast::tcp_stream> stream_;
|
||||
beast::flat_buffer buffer_;
|
||||
std::shared_ptr<std::string const> doc_root_;
|
||||
http::request<http::string_body> req_;
|
||||
@ -387,8 +387,10 @@ public:
|
||||
// Accepts incoming connections and launches the sessions
|
||||
class listener : public std::enable_shared_from_this<listener>
|
||||
{
|
||||
net::io_context& ioc_;
|
||||
ssl::context& ctx_;
|
||||
tcp::acceptor acceptor_;
|
||||
tcp::socket socket_;
|
||||
std::shared_ptr<std::string const> doc_root_;
|
||||
|
||||
public:
|
||||
@ -397,8 +399,10 @@ public:
|
||||
ssl::context& ctx,
|
||||
tcp::endpoint endpoint,
|
||||
std::shared_ptr<std::string const> const& doc_root)
|
||||
: ctx_(ctx)
|
||||
: ioc_(ioc)
|
||||
, ctx_(ctx)
|
||||
, acceptor_(ioc)
|
||||
, socket_(beast::make_strand(ioc))
|
||||
, doc_root_(doc_root)
|
||||
{
|
||||
beast::error_code ec;
|
||||
@ -450,13 +454,14 @@ public:
|
||||
do_accept()
|
||||
{
|
||||
acceptor_.async_accept(
|
||||
socket_,
|
||||
beast::bind_front_handler(
|
||||
&listener::on_accept,
|
||||
shared_from_this()));
|
||||
}
|
||||
|
||||
void
|
||||
on_accept(beast::error_code ec, tcp::socket socket)
|
||||
on_accept(beast::error_code ec)
|
||||
{
|
||||
if(ec)
|
||||
{
|
||||
@ -466,11 +471,14 @@ public:
|
||||
{
|
||||
// Create the session and run it
|
||||
std::make_shared<session>(
|
||||
std::move(socket),
|
||||
std::move(socket_),
|
||||
ctx_,
|
||||
doc_root_)->run();
|
||||
}
|
||||
|
||||
// Make sure each session gets its own strand
|
||||
socket_ = tcp::socket(beast::make_strand(ioc_));
|
||||
|
||||
// Accept another connection
|
||||
do_accept();
|
||||
}
|
||||
|
@ -251,7 +251,7 @@ class session : public std::enable_shared_from_this<session>
|
||||
}
|
||||
};
|
||||
|
||||
beast::tcp_stream<net::io_context::strand> stream_;
|
||||
beast::tcp_stream stream_;
|
||||
beast::flat_buffer buffer_;
|
||||
std::shared_ptr<std::string const> doc_root_;
|
||||
http::request<http::string_body> req_;
|
||||
@ -259,7 +259,7 @@ class session : public std::enable_shared_from_this<session>
|
||||
send_lambda lambda_;
|
||||
|
||||
public:
|
||||
// Take ownership of the socket
|
||||
// Take ownership of the stream
|
||||
session(
|
||||
tcp::socket&& socket,
|
||||
std::shared_ptr<std::string const> const& doc_root)
|
||||
@ -352,7 +352,9 @@ public:
|
||||
// Accepts incoming connections and launches the sessions
|
||||
class listener : public std::enable_shared_from_this<listener>
|
||||
{
|
||||
net::io_context& ioc_;
|
||||
tcp::acceptor acceptor_;
|
||||
tcp::socket socket_;
|
||||
std::shared_ptr<std::string const> doc_root_;
|
||||
|
||||
public:
|
||||
@ -360,7 +362,9 @@ public:
|
||||
net::io_context& ioc,
|
||||
tcp::endpoint endpoint,
|
||||
std::shared_ptr<std::string const> const& doc_root)
|
||||
: acceptor_(ioc)
|
||||
: ioc_(ioc)
|
||||
, acceptor_(beast::make_strand(ioc))
|
||||
, socket_(beast::make_strand(ioc))
|
||||
, doc_root_(doc_root)
|
||||
{
|
||||
beast::error_code ec;
|
||||
@ -412,13 +416,14 @@ public:
|
||||
do_accept()
|
||||
{
|
||||
acceptor_.async_accept(
|
||||
socket_,
|
||||
beast::bind_front_handler(
|
||||
&listener::on_accept,
|
||||
shared_from_this()));
|
||||
}
|
||||
|
||||
void
|
||||
on_accept(beast::error_code ec, tcp::socket socket)
|
||||
on_accept(beast::error_code ec)
|
||||
{
|
||||
if(ec)
|
||||
{
|
||||
@ -428,10 +433,13 @@ public:
|
||||
{
|
||||
// Create the session and run it
|
||||
std::make_shared<session>(
|
||||
std::move(socket),
|
||||
std::move(socket_),
|
||||
doc_root_)->run();
|
||||
}
|
||||
|
||||
// Make sure each session gets its own strand
|
||||
socket_ = tcp::socket(beast::make_strand(ioc_));
|
||||
|
||||
// Accept another connection
|
||||
do_accept();
|
||||
}
|
||||
|
@ -207,11 +207,6 @@ handle_request(
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// The type of stream to use
|
||||
// Stackful coroutines are already stranded.
|
||||
using stream_type =
|
||||
beast::ssl_stream<beast::tcp_stream<net::io_context::executor_type>>;
|
||||
|
||||
// Report a failure
|
||||
void
|
||||
fail(beast::error_code ec, char const* what)
|
||||
@ -223,13 +218,13 @@ fail(beast::error_code ec, char const* what)
|
||||
// The function object is used to send an HTTP message.
|
||||
struct send_lambda
|
||||
{
|
||||
stream_type& stream_;
|
||||
beast::ssl_stream<beast::tcp_stream>& stream_;
|
||||
bool& close_;
|
||||
beast::error_code& ec_;
|
||||
net::yield_context yield_;
|
||||
|
||||
send_lambda(
|
||||
stream_type& stream,
|
||||
beast::ssl_stream<beast::tcp_stream>& stream,
|
||||
bool& close,
|
||||
beast::error_code& ec,
|
||||
net::yield_context yield)
|
||||
@ -258,7 +253,7 @@ struct send_lambda
|
||||
// Handles an HTTP server connection
|
||||
void
|
||||
do_session(
|
||||
stream_type& stream,
|
||||
beast::ssl_stream<beast::tcp_stream>& stream,
|
||||
std::shared_ptr<std::string const> const& doc_root,
|
||||
net::yield_context yield)
|
||||
{
|
||||
@ -357,10 +352,11 @@ do_listen(
|
||||
fail(ec, "accept");
|
||||
else
|
||||
net::spawn(
|
||||
acceptor.get_executor().context(),
|
||||
acceptor.get_executor(),
|
||||
std::bind(
|
||||
&do_session,
|
||||
stream_type(std::move(socket), ctx),
|
||||
beast::ssl_stream<beast::tcp_stream>(
|
||||
std::move(socket), ctx),
|
||||
doc_root,
|
||||
std::placeholders::_1));
|
||||
}
|
||||
|
@ -204,10 +204,6 @@ handle_request(
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// The type of stream to use.
|
||||
// Stackful coroutines are already stranded.
|
||||
using stream_type = beast::tcp_stream<net::io_context::executor_type>;
|
||||
|
||||
// Report a failure
|
||||
void
|
||||
fail(beast::error_code ec, char const* what)
|
||||
@ -219,13 +215,13 @@ fail(beast::error_code ec, char const* what)
|
||||
// The function object is used to send an HTTP message.
|
||||
struct send_lambda
|
||||
{
|
||||
stream_type& stream_;
|
||||
beast::tcp_stream& stream_;
|
||||
bool& close_;
|
||||
beast::error_code& ec_;
|
||||
net::yield_context yield_;
|
||||
|
||||
send_lambda(
|
||||
stream_type& stream,
|
||||
beast::tcp_stream& stream,
|
||||
bool& close,
|
||||
beast::error_code& ec,
|
||||
net::yield_context yield)
|
||||
@ -254,7 +250,7 @@ struct send_lambda
|
||||
// Handles an HTTP server connection
|
||||
void
|
||||
do_session(
|
||||
stream_type& stream,
|
||||
beast::tcp_stream& stream,
|
||||
std::shared_ptr<std::string const> const& doc_root,
|
||||
net::yield_context yield)
|
||||
{
|
||||
@ -339,10 +335,10 @@ do_listen(
|
||||
fail(ec, "accept");
|
||||
else
|
||||
net::spawn(
|
||||
acceptor.get_executor().context(),
|
||||
acceptor.get_executor(),
|
||||
std::bind(
|
||||
&do_session,
|
||||
stream_type(std::move(socket)),
|
||||
beast::tcp_stream(std::move(socket)),
|
||||
doc_root,
|
||||
std::placeholders::_1));
|
||||
}
|
||||
|
@ -99,7 +99,7 @@ private:
|
||||
std::string doc_root_;
|
||||
|
||||
// The socket for the currently connected client.
|
||||
tcp::socket socket_{acceptor_.get_executor().context()};
|
||||
tcp::socket socket_{acceptor_.get_executor()};
|
||||
|
||||
// The buffer for performing reads
|
||||
beast::flat_static_buffer<8192> buffer_;
|
||||
@ -112,7 +112,7 @@ private:
|
||||
|
||||
// The timer putting a time limit on requests.
|
||||
net::basic_waitable_timer<std::chrono::steady_clock> request_deadline_{
|
||||
acceptor_.get_executor().context(), (std::chrono::steady_clock::time_point::max)()};
|
||||
acceptor_.get_executor(), (std::chrono::steady_clock::time_point::max)()};
|
||||
|
||||
// The string-based response message.
|
||||
boost::optional<http::response<http::string_body, http::basic_fields<alloc_t>>> string_response_;
|
||||
|
@ -208,13 +208,6 @@ handle_request(
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// The type of plain streams
|
||||
using plain_stream_type = beast::tcp_stream<net::io_context::strand>;
|
||||
|
||||
// The type of TLS streams
|
||||
using ssl_stream_type =
|
||||
beast::ssl_stream<beast::tcp_stream<net::io_context::strand>>;
|
||||
|
||||
// Report a failure
|
||||
void
|
||||
fail(beast::error_code ec, char const* what)
|
||||
@ -358,7 +351,7 @@ class plain_session
|
||||
: public session<plain_session>
|
||||
, public std::enable_shared_from_this<plain_session>
|
||||
{
|
||||
plain_stream_type stream_;
|
||||
beast::tcp_stream stream_;
|
||||
|
||||
public:
|
||||
// Create the session
|
||||
@ -374,7 +367,7 @@ public:
|
||||
}
|
||||
|
||||
// Called by the base class
|
||||
plain_stream_type&
|
||||
beast::tcp_stream&
|
||||
stream()
|
||||
{
|
||||
return stream_;
|
||||
@ -403,7 +396,7 @@ class ssl_session
|
||||
: public session<ssl_session>
|
||||
, public std::enable_shared_from_this<ssl_session>
|
||||
{
|
||||
ssl_stream_type stream_;
|
||||
beast::ssl_stream<beast::tcp_stream> stream_;
|
||||
|
||||
public:
|
||||
// Create the session
|
||||
@ -420,7 +413,7 @@ public:
|
||||
}
|
||||
|
||||
// Called by the base class
|
||||
ssl_stream_type&
|
||||
beast::ssl_stream<beast::tcp_stream>&
|
||||
stream()
|
||||
{
|
||||
return stream_;
|
||||
@ -442,6 +435,7 @@ public:
|
||||
&ssl_session::on_handshake,
|
||||
shared_from_this()));
|
||||
}
|
||||
|
||||
void
|
||||
on_handshake(
|
||||
beast::error_code ec,
|
||||
@ -484,14 +478,14 @@ public:
|
||||
// Detects SSL handshakes
|
||||
class detect_session : public std::enable_shared_from_this<detect_session>
|
||||
{
|
||||
plain_stream_type stream_;
|
||||
beast::tcp_stream stream_;
|
||||
ssl::context& ctx_;
|
||||
std::shared_ptr<std::string const> doc_root_;
|
||||
beast::flat_buffer buffer_;
|
||||
|
||||
public:
|
||||
detect_session(
|
||||
tcp::socket socket,
|
||||
tcp::socket&& socket,
|
||||
ssl::context& ctx,
|
||||
std::shared_ptr<std::string const> const& doc_root)
|
||||
: stream_(std::move(socket))
|
||||
@ -544,8 +538,10 @@ public:
|
||||
// Accepts incoming connections and launches the sessions
|
||||
class listener : public std::enable_shared_from_this<listener>
|
||||
{
|
||||
net::io_context& ioc_;
|
||||
ssl::context& ctx_;
|
||||
tcp::acceptor acceptor_;
|
||||
tcp::socket socket_;
|
||||
std::shared_ptr<std::string const> doc_root_;
|
||||
|
||||
public:
|
||||
@ -554,8 +550,10 @@ public:
|
||||
ssl::context& ctx,
|
||||
tcp::endpoint endpoint,
|
||||
std::shared_ptr<std::string const> const& doc_root)
|
||||
: ctx_(ctx)
|
||||
, acceptor_(ioc)
|
||||
: ioc_(ioc)
|
||||
, ctx_(ctx)
|
||||
, acceptor_(beast::make_strand(ioc))
|
||||
, socket_(beast::make_strand(ioc))
|
||||
, doc_root_(doc_root)
|
||||
{
|
||||
beast::error_code ec;
|
||||
@ -607,13 +605,14 @@ public:
|
||||
do_accept()
|
||||
{
|
||||
acceptor_.async_accept(
|
||||
socket_,
|
||||
beast::bind_front_handler(
|
||||
&listener::on_accept,
|
||||
shared_from_this()));
|
||||
}
|
||||
|
||||
void
|
||||
on_accept(beast::error_code ec, tcp::socket sock)
|
||||
on_accept(beast::error_code ec)
|
||||
{
|
||||
if(ec)
|
||||
{
|
||||
@ -623,11 +622,14 @@ public:
|
||||
{
|
||||
// Create the detector session and run it
|
||||
std::make_shared<detect_session>(
|
||||
std::move(sock),
|
||||
std::move(socket_),
|
||||
ctx_,
|
||||
doc_root_)->run();
|
||||
}
|
||||
|
||||
// Make sure each session gets its own strand
|
||||
socket_ = tcp::socket(beast::make_strand(ioc_));
|
||||
|
||||
// Accept another connection
|
||||
do_accept();
|
||||
}
|
||||
|
@ -76,7 +76,7 @@ private:
|
||||
|
||||
// The timer for putting a deadline on connection processing.
|
||||
net::basic_waitable_timer<std::chrono::steady_clock> deadline_{
|
||||
socket_.get_executor().context(), std::chrono::seconds(60)};
|
||||
socket_.get_executor(), std::chrono::seconds(60)};
|
||||
|
||||
// Asynchronously receive a complete request message.
|
||||
void
|
||||
|
@ -209,10 +209,6 @@ handle_request(
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// The type of TLS streams
|
||||
using ssl_stream_type =
|
||||
beast::ssl_stream<beast::tcp_stream<net::io_context::strand>>;
|
||||
|
||||
// Report a failure
|
||||
void
|
||||
fail(beast::error_code ec, char const* what)
|
||||
@ -264,7 +260,7 @@ class session
|
||||
}
|
||||
};
|
||||
|
||||
ssl_stream_type stream_;
|
||||
beast::ssl_stream<beast::tcp_stream> stream_;
|
||||
beast::flat_buffer buffer_;
|
||||
std::shared_ptr<std::string const> doc_root_;
|
||||
http::request<http::string_body> req_;
|
||||
@ -383,6 +379,7 @@ class listener
|
||||
: public net::coroutine
|
||||
, public std::enable_shared_from_this<listener>
|
||||
{
|
||||
net::io_context& ioc_;
|
||||
ssl::context& ctx_;
|
||||
tcp::acceptor acceptor_;
|
||||
tcp::socket socket_;
|
||||
@ -394,9 +391,10 @@ public:
|
||||
ssl::context& ctx,
|
||||
tcp::endpoint endpoint,
|
||||
std::shared_ptr<std::string const> const& doc_root)
|
||||
: ctx_(ctx)
|
||||
, acceptor_(ioc)
|
||||
, socket_(ioc)
|
||||
: ioc_(ioc)
|
||||
, ctx_(ctx)
|
||||
, acceptor_(beast::make_strand(ioc))
|
||||
, socket_(beast::make_strand(ioc))
|
||||
, doc_root_(doc_root)
|
||||
{
|
||||
beast::error_code ec;
|
||||
@ -470,6 +468,9 @@ public:
|
||||
ctx_,
|
||||
doc_root_)->run();
|
||||
}
|
||||
|
||||
// Make sure each session gets its own strand
|
||||
socket_ = tcp::socket(beast::make_strand(ioc_));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -205,9 +205,6 @@ handle_request(
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// The type of stream to use
|
||||
using stream_type = beast::tcp_stream<net::io_context::strand>;
|
||||
|
||||
// Report a failure
|
||||
void
|
||||
fail(beast::error_code ec, char const* what)
|
||||
@ -258,7 +255,7 @@ class session
|
||||
}
|
||||
};
|
||||
|
||||
stream_type stream_;
|
||||
beast::tcp_stream stream_;
|
||||
beast::flat_buffer buffer_;
|
||||
std::shared_ptr<std::string const> doc_root_;
|
||||
http::request<http::string_body> req_;
|
||||
@ -269,7 +266,7 @@ public:
|
||||
// Take ownership of the socket
|
||||
explicit
|
||||
session(
|
||||
tcp::socket socket,
|
||||
tcp::socket&& socket,
|
||||
std::shared_ptr<std::string const> const& doc_root)
|
||||
: stream_(std::move(socket))
|
||||
, doc_root_(doc_root)
|
||||
@ -348,6 +345,7 @@ class listener
|
||||
: public net::coroutine
|
||||
, public std::enable_shared_from_this<listener>
|
||||
{
|
||||
net::io_context& ioc_;
|
||||
tcp::acceptor acceptor_;
|
||||
tcp::socket socket_;
|
||||
std::shared_ptr<std::string const> doc_root_;
|
||||
@ -357,8 +355,9 @@ public:
|
||||
net::io_context& ioc,
|
||||
tcp::endpoint endpoint,
|
||||
std::shared_ptr<std::string const> const& doc_root)
|
||||
: acceptor_(ioc)
|
||||
, socket_(ioc)
|
||||
: ioc_(ioc)
|
||||
, acceptor_(beast::make_strand(ioc))
|
||||
, socket_(beast::make_strand(ioc))
|
||||
, doc_root_(doc_root)
|
||||
{
|
||||
beast::error_code ec;
|
||||
@ -429,6 +428,9 @@ public:
|
||||
std::move(socket_),
|
||||
doc_root_)->run();
|
||||
}
|
||||
|
||||
// Make sure each session gets its own strand
|
||||
socket_ = tcp::socket(beast::make_strand(ioc_));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -45,8 +45,8 @@ fail(beast::error_code ec, char const* what)
|
||||
class session : public std::enable_shared_from_this<session>
|
||||
{
|
||||
tcp::resolver resolver_;
|
||||
websocket::stream<beast::ssl_stream<
|
||||
beast::tcp_stream<net::io_context::executor_type>>> ws_;
|
||||
websocket::stream<
|
||||
beast::ssl_stream<beast::tcp_stream>> ws_;
|
||||
beast::multi_buffer buffer_;
|
||||
std::string host_;
|
||||
std::string text_;
|
||||
@ -55,8 +55,8 @@ public:
|
||||
// Resolver and socket require an io_context
|
||||
explicit
|
||||
session(net::io_context& ioc, ssl::context& ctx)
|
||||
: resolver_(ioc)
|
||||
, ws_(ioc, ctx)
|
||||
: resolver_(beast::make_strand(ioc))
|
||||
, ws_(beast::make_strand(ioc), ctx)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -40,8 +40,7 @@ fail(beast::error_code ec, char const* what)
|
||||
class session : public std::enable_shared_from_this<session>
|
||||
{
|
||||
tcp::resolver resolver_;
|
||||
websocket::stream<
|
||||
beast::tcp_stream<net::io_context::executor_type>> ws_;
|
||||
websocket::stream<beast::tcp_stream> ws_;
|
||||
beast::multi_buffer buffer_;
|
||||
std::string host_;
|
||||
std::string text_;
|
||||
@ -50,8 +49,8 @@ public:
|
||||
// Resolver and socket require an io_context
|
||||
explicit
|
||||
session(net::io_context& ioc)
|
||||
: resolver_(ioc)
|
||||
, ws_(ioc)
|
||||
: resolver_(beast::make_strand(ioc))
|
||||
, ws_(beast::make_strand(ioc))
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -54,9 +54,9 @@ do_session(
|
||||
beast::error_code ec;
|
||||
|
||||
// These objects perform our I/O
|
||||
tcp::resolver resolver{ioc};
|
||||
websocket::stream<beast::ssl_stream<
|
||||
beast::tcp_stream<net::io_context::executor_type>>> ws(ioc, ctx);
|
||||
tcp::resolver resolver(ioc);
|
||||
websocket::stream<
|
||||
beast::ssl_stream<beast::tcp_stream>> ws(ioc, ctx);
|
||||
|
||||
// Look up the domain name
|
||||
auto const results = resolver.async_resolve(host, port, yield[ec]);
|
||||
|
@ -48,9 +48,8 @@ do_session(
|
||||
beast::error_code ec;
|
||||
|
||||
// These objects perform our I/O
|
||||
tcp::resolver resolver{ioc};
|
||||
websocket::stream<
|
||||
beast::tcp_stream<net::io_context::executor_type>> ws(ioc);
|
||||
tcp::resolver resolver(ioc);
|
||||
websocket::stream<beast::tcp_stream> ws(ioc);
|
||||
|
||||
// Look up the domain name
|
||||
auto const results = resolver.async_resolve(host, port, yield[ec]);
|
||||
|
@ -48,13 +48,13 @@ 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<beast::ssl_stream<
|
||||
beast::tcp_stream<net::io_context::strand>>> ws_;
|
||||
websocket::stream<
|
||||
beast::ssl_stream<beast::tcp_stream>> ws_;
|
||||
beast::multi_buffer buffer_;
|
||||
|
||||
public:
|
||||
// Take ownership of the socket
|
||||
session(tcp::socket socket, ssl::context& ctx)
|
||||
session(tcp::socket&& socket, ssl::context& ctx)
|
||||
: ws_(std::move(socket), ctx)
|
||||
{
|
||||
}
|
||||
@ -172,16 +172,20 @@ public:
|
||||
// Accepts incoming connections and launches the sessions
|
||||
class listener : public std::enable_shared_from_this<listener>
|
||||
{
|
||||
net::io_context& ioc_;
|
||||
ssl::context& ctx_;
|
||||
tcp::acceptor acceptor_;
|
||||
tcp::socket socket_;
|
||||
|
||||
public:
|
||||
listener(
|
||||
net::io_context& ioc,
|
||||
ssl::context& ctx,
|
||||
tcp::endpoint endpoint)
|
||||
: ctx_(ctx)
|
||||
, acceptor_(ioc)
|
||||
: ioc_(ioc)
|
||||
, ctx_(ctx)
|
||||
, acceptor_(beast::make_strand(ioc))
|
||||
, socket_(beast::make_strand(ioc))
|
||||
{
|
||||
beast::error_code ec;
|
||||
|
||||
@ -232,13 +236,14 @@ public:
|
||||
do_accept()
|
||||
{
|
||||
acceptor_.async_accept(
|
||||
socket_,
|
||||
beast::bind_front_handler(
|
||||
&listener::on_accept,
|
||||
shared_from_this()));
|
||||
}
|
||||
|
||||
void
|
||||
on_accept(beast::error_code ec, tcp::socket socket)
|
||||
on_accept(beast::error_code ec)
|
||||
{
|
||||
if(ec)
|
||||
{
|
||||
@ -247,9 +252,12 @@ 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();
|
||||
}
|
||||
|
||||
// Make sure each session gets its own strand
|
||||
socket_ = tcp::socket(beast::make_strand(ioc_));
|
||||
|
||||
// Accept another connection
|
||||
do_accept();
|
||||
}
|
||||
|
@ -43,13 +43,13 @@ 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<beast::tcp_stream<net::io_context::strand>> ws_;
|
||||
websocket::stream<beast::tcp_stream> ws_;
|
||||
beast::multi_buffer buffer_;
|
||||
|
||||
public:
|
||||
// Take ownership of the socket
|
||||
explicit
|
||||
session(tcp::socket socket)
|
||||
session(tcp::socket&& socket)
|
||||
: ws_(std::move(socket))
|
||||
{
|
||||
}
|
||||
@ -146,13 +146,17 @@ public:
|
||||
// Accepts incoming connections and launches the sessions
|
||||
class listener : public std::enable_shared_from_this<listener>
|
||||
{
|
||||
net::io_context& ioc_;
|
||||
tcp::acceptor acceptor_;
|
||||
tcp::socket socket_;
|
||||
|
||||
public:
|
||||
listener(
|
||||
net::io_context& ioc,
|
||||
tcp::endpoint endpoint)
|
||||
: acceptor_(ioc)
|
||||
: ioc_(ioc)
|
||||
, acceptor_(ioc)
|
||||
, socket_(beast::make_strand(ioc_))
|
||||
{
|
||||
beast::error_code ec;
|
||||
|
||||
@ -203,13 +207,14 @@ public:
|
||||
do_accept()
|
||||
{
|
||||
acceptor_.async_accept(
|
||||
socket_,
|
||||
beast::bind_front_handler(
|
||||
&listener::on_accept,
|
||||
shared_from_this()));
|
||||
}
|
||||
|
||||
void
|
||||
on_accept(beast::error_code ec, tcp::socket socket)
|
||||
on_accept(beast::error_code ec)
|
||||
{
|
||||
if(ec)
|
||||
{
|
||||
@ -218,9 +223,12 @@ public:
|
||||
else
|
||||
{
|
||||
// Create the session and run it
|
||||
std::make_shared<session>(std::move(socket))->run();
|
||||
std::make_shared<session>(std::move(socket_))->run();
|
||||
}
|
||||
|
||||
// Make sure each session gets its own strand
|
||||
socket_ = tcp::socket(beast::make_strand(ioc_));
|
||||
|
||||
// Accept another connection
|
||||
do_accept();
|
||||
}
|
||||
|
@ -21,7 +21,7 @@
|
||||
*/
|
||||
class http_session : public boost::enable_shared_from_this<http_session>
|
||||
{
|
||||
beast::tcp_stream<net::io_context::strand> stream_;
|
||||
beast::tcp_stream stream_;
|
||||
beast::flat_buffer buffer_;
|
||||
boost::shared_ptr<shared_state> state_;
|
||||
http::request<http::string_body> req_;
|
||||
|
@ -16,7 +16,9 @@ listener(
|
||||
net::io_context& ioc,
|
||||
tcp::endpoint endpoint,
|
||||
boost::shared_ptr<shared_state> const& state)
|
||||
: acceptor_(ioc)
|
||||
: ioc_(ioc)
|
||||
, acceptor_(ioc)
|
||||
, socket_(beast::make_strand(ioc))
|
||||
, state_(state)
|
||||
{
|
||||
beast::error_code ec;
|
||||
@ -61,6 +63,7 @@ run()
|
||||
{
|
||||
// Start accepting a connection
|
||||
acceptor_.async_accept(
|
||||
socket_,
|
||||
beast::bind_front_handler(
|
||||
&listener::on_accept,
|
||||
shared_from_this()));
|
||||
@ -80,18 +83,22 @@ fail(beast::error_code ec, char const* what)
|
||||
// Handle a connection
|
||||
void
|
||||
listener::
|
||||
on_accept(beast::error_code ec, tcp::socket socket)
|
||||
on_accept(beast::error_code ec)
|
||||
{
|
||||
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();
|
||||
|
||||
// Make sure each session gets its own strand
|
||||
socket_ = tcp::socket(beast::make_strand(ioc_));
|
||||
|
||||
// Accept another connection
|
||||
acceptor_.async_accept(
|
||||
socket_,
|
||||
beast::bind_front_handler(
|
||||
&listener::on_accept,
|
||||
shared_from_this()));
|
||||
|
@ -22,11 +22,13 @@ class shared_state;
|
||||
// Accepts incoming connections and launches the sessions
|
||||
class listener : public boost::enable_shared_from_this<listener>
|
||||
{
|
||||
net::io_context& ioc_;
|
||||
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, tcp::socket socket);
|
||||
void on_accept(beast::error_code ec);
|
||||
|
||||
public:
|
||||
listener(
|
||||
|
@ -83,17 +83,22 @@ void
|
||||
websocket_session::
|
||||
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(! ws_.get_executor().running_in_this_thread())
|
||||
return net::post(
|
||||
ws_.get_executor(),
|
||||
beast::bind_front_handler(
|
||||
&websocket_session::send,
|
||||
shared_from_this(),
|
||||
ss));
|
||||
// Post our work to the strand, this ensures
|
||||
// that the members of `this` will not be
|
||||
// accessed concurrently.
|
||||
|
||||
net::post(
|
||||
ws_.get_executor(),
|
||||
beast::bind_front_handler(
|
||||
&websocket_session::on_send,
|
||||
shared_from_this(),
|
||||
ss));
|
||||
}
|
||||
|
||||
void
|
||||
websocket_session::
|
||||
on_send(boost::shared_ptr<std::string const> const& ss)
|
||||
{
|
||||
// Always add to queue
|
||||
queue_.push_back(ss);
|
||||
|
||||
|
@ -27,7 +27,7 @@ class shared_state;
|
||||
class websocket_session : public boost::enable_shared_from_this<websocket_session>
|
||||
{
|
||||
beast::flat_buffer buffer_;
|
||||
websocket::stream<beast::tcp_stream<net::io_context::strand>> ws_;
|
||||
websocket::stream<beast::tcp_stream> ws_;
|
||||
boost::shared_ptr<shared_state> state_;
|
||||
std::vector<boost::shared_ptr<std::string const>> queue_;
|
||||
|
||||
@ -50,6 +50,10 @@ public:
|
||||
// Send a message
|
||||
void
|
||||
send(boost::shared_ptr<std::string const> const& ss);
|
||||
|
||||
private:
|
||||
void
|
||||
on_send(boost::shared_ptr<std::string const> const& ss);
|
||||
};
|
||||
|
||||
template<class Body, class Allocator>
|
||||
|
@ -38,11 +38,6 @@ 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)
|
||||
@ -53,7 +48,8 @@ fail(beast::error_code ec, char const* what)
|
||||
// Echoes back all received WebSocket messages
|
||||
void
|
||||
do_session(
|
||||
ws_type& ws,
|
||||
websocket::stream<
|
||||
beast::ssl_stream<beast::tcp_stream>>& ws,
|
||||
net::yield_context yield)
|
||||
{
|
||||
beast::error_code ec;
|
||||
@ -153,10 +149,11 @@ do_listen(
|
||||
fail(ec, "accept");
|
||||
else
|
||||
net::spawn(
|
||||
acceptor.get_executor().context(),
|
||||
acceptor.get_executor(),
|
||||
std::bind(
|
||||
&do_session,
|
||||
ws_type(std::move(socket), ctx),
|
||||
websocket::stream<beast::ssl_stream<
|
||||
beast::tcp_stream>>(std::move(socket), ctx),
|
||||
std::placeholders::_1));
|
||||
}
|
||||
}
|
||||
|
@ -33,11 +33,6 @@ 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)
|
||||
@ -47,7 +42,9 @@ fail(beast::error_code ec, char const* what)
|
||||
|
||||
// Echoes back all received WebSocket messages
|
||||
void
|
||||
do_session(ws_type& ws, net::yield_context yield)
|
||||
do_session(
|
||||
websocket::stream<beast::tcp_stream>& ws,
|
||||
net::yield_context yield)
|
||||
{
|
||||
beast::error_code ec;
|
||||
|
||||
@ -133,10 +130,11 @@ do_listen(
|
||||
fail(ec, "accept");
|
||||
else
|
||||
net::spawn(
|
||||
acceptor.get_executor().context(),
|
||||
acceptor.get_executor(),
|
||||
std::bind(
|
||||
&do_session,
|
||||
ws_type(std::move(socket)),
|
||||
websocket::stream<
|
||||
beast::tcp_stream>(std::move(socket)),
|
||||
std::placeholders::_1));
|
||||
}
|
||||
}
|
||||
@ -157,7 +155,7 @@ int main(int argc, char* argv[])
|
||||
auto const threads = std::max<int>(1, std::atoi(argv[3]));
|
||||
|
||||
// The io_context is required for all I/O
|
||||
net::io_context ioc{threads};
|
||||
net::io_context ioc(threads);
|
||||
|
||||
// Spawn a listening port
|
||||
net::spawn(ioc,
|
||||
|
@ -78,13 +78,8 @@ 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(ws_type& ws)
|
||||
do_sync_session(websocket::stream<beast::tcp_stream>& ws)
|
||||
{
|
||||
beast::error_code ec;
|
||||
|
||||
@ -135,7 +130,8 @@ do_sync_listen(
|
||||
|
||||
std::thread(std::bind(
|
||||
&do_sync_session,
|
||||
ws_type(std::move(socket)))).detach();
|
||||
websocket::stream<beast::tcp_stream>(
|
||||
std::move(socket)))).detach();
|
||||
}
|
||||
}
|
||||
|
||||
@ -144,13 +140,13 @@ do_sync_listen(
|
||||
// Echoes back all received WebSocket messages
|
||||
class async_session : public std::enable_shared_from_this<async_session>
|
||||
{
|
||||
websocket::stream<beast::tcp_stream<net::io_context::strand>> ws_;
|
||||
websocket::stream<beast::tcp_stream> ws_;
|
||||
beast::multi_buffer buffer_;
|
||||
|
||||
public:
|
||||
// Take ownership of the socket
|
||||
explicit
|
||||
async_session(tcp::socket socket)
|
||||
async_session(tcp::socket&& socket)
|
||||
: ws_(std::move(socket))
|
||||
{
|
||||
setup_stream(ws_);
|
||||
@ -160,6 +156,11 @@ public:
|
||||
void
|
||||
run()
|
||||
{
|
||||
// Set suggested timeout settings for the websocket
|
||||
ws_.set_option(
|
||||
websocket::stream_base::suggested_settings(
|
||||
websocket::role_type::server));
|
||||
|
||||
// Set a decorator to change the Server of the handshake
|
||||
ws_.set_option(websocket::stream_base::decorator(
|
||||
[](websocket::response_type& res)
|
||||
@ -240,13 +241,17 @@ public:
|
||||
// Accepts incoming connections and launches the sessions
|
||||
class async_listener : public std::enable_shared_from_this<async_listener>
|
||||
{
|
||||
net::io_context& ioc_;
|
||||
tcp::acceptor acceptor_;
|
||||
tcp::socket socket_;
|
||||
|
||||
public:
|
||||
async_listener(
|
||||
net::io_context& ioc,
|
||||
tcp::endpoint endpoint)
|
||||
: acceptor_(ioc)
|
||||
: ioc_(ioc)
|
||||
, acceptor_(beast::make_strand(ioc))
|
||||
, socket_(beast::make_strand(ioc))
|
||||
{
|
||||
beast::error_code ec;
|
||||
|
||||
@ -297,13 +302,14 @@ public:
|
||||
do_accept()
|
||||
{
|
||||
acceptor_.async_accept(
|
||||
socket_,
|
||||
beast::bind_front_handler(
|
||||
&async_listener::on_accept,
|
||||
shared_from_this()));
|
||||
}
|
||||
|
||||
void
|
||||
on_accept(beast::error_code ec, tcp::socket socket)
|
||||
on_accept(beast::error_code ec)
|
||||
{
|
||||
if(ec)
|
||||
{
|
||||
@ -312,9 +318,12 @@ 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();
|
||||
}
|
||||
|
||||
// Make sure each session gets its own strand
|
||||
socket_ = tcp::socket(beast::make_strand(ioc_));
|
||||
|
||||
// Accept another connection
|
||||
do_accept();
|
||||
}
|
||||
@ -323,12 +332,19 @@ public:
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
do_coro_session(ws_type& ws, net::yield_context yield)
|
||||
do_coro_session(
|
||||
websocket::stream<beast::tcp_stream>& ws,
|
||||
net::yield_context yield)
|
||||
{
|
||||
beast::error_code ec;
|
||||
|
||||
setup_stream(ws);
|
||||
|
||||
// Set suggested timeout settings for the websocket
|
||||
ws.set_option(
|
||||
websocket::stream_base::suggested_settings(
|
||||
websocket::role_type::server));
|
||||
|
||||
// Set a decorator to change the Server of the handshake
|
||||
ws.set_option(websocket::stream_base::decorator(
|
||||
[](websocket::response_type& res)
|
||||
@ -395,10 +411,11 @@ do_coro_listen(
|
||||
}
|
||||
|
||||
net::spawn(
|
||||
acceptor.get_executor().context(),
|
||||
acceptor.get_executor(),
|
||||
std::bind(
|
||||
&do_coro_session,
|
||||
ws_type(std::move(socket)),
|
||||
websocket::stream<
|
||||
beast::tcp_stream>(std::move(socket)),
|
||||
std::placeholders::_1));
|
||||
}
|
||||
}
|
||||
|
@ -51,8 +51,7 @@ class session
|
||||
: public net::coroutine
|
||||
, public std::enable_shared_from_this<session>
|
||||
{
|
||||
websocket::stream<beast::ssl_stream<
|
||||
beast::tcp_stream<net::io_context::strand>>> ws_;
|
||||
websocket::stream<beast::ssl_stream<beast::tcp_stream>> ws_;
|
||||
beast::multi_buffer buffer_;
|
||||
|
||||
public:
|
||||
@ -166,6 +165,7 @@ class listener
|
||||
: public net::coroutine
|
||||
, public std::enable_shared_from_this<listener>
|
||||
{
|
||||
net::io_context& ioc_;
|
||||
ssl::context& ctx_;
|
||||
tcp::acceptor acceptor_;
|
||||
tcp::socket socket_;
|
||||
@ -175,7 +175,8 @@ public:
|
||||
net::io_context& ioc,
|
||||
ssl::context& ctx,
|
||||
tcp::endpoint endpoint)
|
||||
: ctx_(ctx)
|
||||
: ioc_(ioc)
|
||||
, ctx_(ctx)
|
||||
, acceptor_(ioc)
|
||||
, socket_(ioc)
|
||||
{
|
||||
@ -247,6 +248,9 @@ public:
|
||||
// Create the session and run it
|
||||
std::make_shared<session>(std::move(socket_), ctx_)->run();
|
||||
}
|
||||
|
||||
// Make sure each session gets its own strand
|
||||
socket_ = tcp::socket(beast::make_strand(ioc_));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -46,8 +46,7 @@ class session
|
||||
: public net::coroutine
|
||||
, public std::enable_shared_from_this<session>
|
||||
{
|
||||
websocket::stream<
|
||||
beast::tcp_stream<net::io_context::strand>> ws_;
|
||||
websocket::stream<beast::tcp_stream> ws_;
|
||||
beast::multi_buffer buffer_;
|
||||
|
||||
public:
|
||||
@ -143,6 +142,7 @@ class listener
|
||||
: public net::coroutine
|
||||
, public std::enable_shared_from_this<listener>
|
||||
{
|
||||
net::io_context& ioc_;
|
||||
tcp::acceptor acceptor_;
|
||||
tcp::socket socket_;
|
||||
|
||||
@ -150,8 +150,9 @@ public:
|
||||
listener(
|
||||
net::io_context& ioc,
|
||||
tcp::endpoint endpoint)
|
||||
: acceptor_(ioc)
|
||||
, socket_(ioc)
|
||||
: ioc_(ioc)
|
||||
, acceptor_(beast::make_strand(ioc))
|
||||
, socket_(beast::make_strand(ioc))
|
||||
{
|
||||
beast::error_code ec;
|
||||
|
||||
@ -221,6 +222,9 @@ public:
|
||||
// Create the session and run it
|
||||
std::make_shared<session>(std::move(socket_))->run();
|
||||
}
|
||||
|
||||
// Make sure each session gets its own strand
|
||||
socket_ = tcp::socket(beast::make_strand(ioc_));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
#define BOOST_BEAST_TEST_TCP_HPP
|
||||
|
||||
#include <boost/beast/core/detail/config.hpp>
|
||||
#include <boost/beast/core/detail/get_io_context.hpp>
|
||||
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
||||
#include <boost/beast/_experimental/test/handler.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
@ -60,26 +61,28 @@ run_for(
|
||||
ioc.restart();
|
||||
}
|
||||
|
||||
/** Connect two TCP/IP sockets together.
|
||||
/** Connect two TCP sockets together.
|
||||
*/
|
||||
inline
|
||||
template<class Executor>
|
||||
bool
|
||||
connect(
|
||||
net::ip::tcp::socket& s1,
|
||||
net::ip::tcp::socket& s2)
|
||||
net::basic_stream_socket<net::ip::tcp, Executor>& s1,
|
||||
net::basic_stream_socket<net::ip::tcp, Executor>& s2)
|
||||
|
||||
{
|
||||
// Sockets must use the same I/O context
|
||||
BOOST_ASSERT(
|
||||
std::addressof(s1.get_executor().context()) ==
|
||||
std::addressof(s2.get_executor().context()));
|
||||
auto& ioc = s1.get_executor().context();
|
||||
s1 = net::ip::tcp::socket(ioc);
|
||||
s2 = net::ip::tcp::socket(ioc);
|
||||
auto ioc1 = beast::detail::get_io_context(s1);
|
||||
auto ioc2 = beast::detail::get_io_context(s2);
|
||||
if(! BEAST_EXPECT(ioc1 != nullptr))
|
||||
return false;
|
||||
if(! BEAST_EXPECT(ioc2 != nullptr))
|
||||
return false;
|
||||
if(! BEAST_EXPECT(ioc1 == ioc2))
|
||||
return false;
|
||||
auto& ioc = *ioc1;
|
||||
try
|
||||
{
|
||||
net::ip::tcp::acceptor a(
|
||||
s1.get_executor().context());
|
||||
net::basic_socket_acceptor<
|
||||
net::ip::tcp, Executor> a(s1.get_executor());
|
||||
auto ep = net::ip::tcp::endpoint(
|
||||
net::ip::make_address_v4("127.0.0.1"), 0);
|
||||
a.open(ep.protocol());
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include <boost/beast/core/detail/config.hpp>
|
||||
#include <boost/beast/core/detail/stream_base.hpp>
|
||||
#include <boost/beast/core/error.hpp>
|
||||
#include <boost/beast/core/stream_traits.hpp>
|
||||
#include <boost/beast/websocket/role.hpp> // VFALCO This is unfortunate
|
||||
#include <boost/asio/async_result.hpp>
|
||||
#include <boost/asio/basic_stream_socket.hpp>
|
||||
@ -21,7 +22,6 @@
|
||||
#include <boost/asio/is_executor.hpp>
|
||||
#include <boost/core/empty_value.hpp>
|
||||
#include <boost/config/workaround.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/enable_shared_from_this.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <chrono>
|
||||
@ -42,14 +42,14 @@ namespace beast {
|
||||
/** A stream socket wrapper with timeouts and associated executor.
|
||||
|
||||
This stream wraps a `net::basic_stream_socket` to provide
|
||||
the following additional features:
|
||||
the following features:
|
||||
|
||||
@li Optional timeouts may be specified for each logical asynchronous
|
||||
operation performing any reading, writing, or connecting.
|
||||
|
||||
@li An <em>Executor</em> may be associated with the stream, which will
|
||||
be used to invoke any completion handlers which do not already have
|
||||
an associated executor. This achieves partial support for
|
||||
an associated executor. This achieves support for
|
||||
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1322r0.html">[P1322R0] Networking TS enhancement to enable custom I/O executors</a>.
|
||||
|
||||
Although the stream supports multiple concurrent outstanding asynchronous
|
||||
@ -109,7 +109,7 @@ namespace beast {
|
||||
HTTP response with a different timeout.
|
||||
|
||||
@code
|
||||
void process_http_1 (tcp_stream<net::io_context::executor_type>& stream, net::yield_context yield)
|
||||
void process_http_1 (tcp_stream& stream, net::yield_context yield)
|
||||
{
|
||||
flat_buffer buffer;
|
||||
http::request<http::empty_body> req;
|
||||
@ -133,7 +133,7 @@ namespace beast {
|
||||
applies to the entire combined operation of reading and writing:
|
||||
|
||||
@code
|
||||
void process_http_2 (tcp_stream<net::io_context::executor_type>& stream, net::yield_context yield)
|
||||
void process_http_2 (tcp_stream& stream, net::yield_context yield)
|
||||
{
|
||||
flat_buffer buffer;
|
||||
http::request<http::empty_body> req;
|
||||
@ -155,7 +155,7 @@ namespace beast {
|
||||
thusly:
|
||||
|
||||
@code
|
||||
void do_ssl_handshake (net::ssl::stream<tcp_stream<net::io_context::executor_type>>& stream, net::yield_context yield)
|
||||
void do_ssl_handshake (net::ssl::stream<tcp_stream>& stream, net::yield_context yield)
|
||||
{
|
||||
// Require that the SSL handshake take no longer than 10 seconds
|
||||
stream.expires_after(std::chrono::seconds(10));
|
||||
@ -176,7 +176,8 @@ namespace beast {
|
||||
|
||||
@tparam Executor A type meeting the requirements of <em>Executor</em> to
|
||||
be used for submitting all completion handlers which do not already have an
|
||||
associated executor.
|
||||
associated executor. If this type is omitted, the default of `net::executor`
|
||||
will be used.
|
||||
|
||||
@par Thread Safety
|
||||
<em>Distinct objects</em>: Safe.@n
|
||||
@ -190,12 +191,33 @@ namespace beast {
|
||||
|
||||
@li <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1322r0.html">[P1322R0] Networking TS enhancement to enable custom I/O executors</a>.
|
||||
*/
|
||||
template<class Protocol, class Executor>
|
||||
template<
|
||||
class Protocol,
|
||||
class Executor = net::executor>
|
||||
class basic_stream
|
||||
#if ! BOOST_BEAST_DOXYGEN
|
||||
: private detail::stream_base
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
/// The type of the underlying socket.
|
||||
using socket_type =
|
||||
net::basic_stream_socket<Protocol, Executor>;
|
||||
|
||||
/** The type of the executor associated with the stream.
|
||||
|
||||
This will be the type of executor used to invoke completion
|
||||
handlers which do not have an explicit associated executor.
|
||||
*/
|
||||
using executor_type = beast::executor_type<socket_type>;
|
||||
|
||||
/// The protocol type.
|
||||
using protocol_type = Protocol;
|
||||
|
||||
/// The endpoint type.
|
||||
using endpoint_type = typename Protocol::endpoint;
|
||||
|
||||
private:
|
||||
static_assert(net::is_executor<Executor>::value,
|
||||
"Executor requirements not met");
|
||||
|
||||
@ -206,33 +228,26 @@ public:
|
||||
#endif
|
||||
struct impl_type
|
||||
: boost::enable_shared_from_this<impl_type>
|
||||
, boost::empty_value<Executor>
|
||||
{
|
||||
// must come first
|
||||
net::basic_stream_socket<
|
||||
Protocol, Executor> socket;
|
||||
|
||||
op_state read;
|
||||
op_state write;
|
||||
|
||||
net::basic_stream_socket<Protocol> socket;
|
||||
|
||||
impl_type(impl_type&&) = default;
|
||||
|
||||
template<class... Args>
|
||||
explicit
|
||||
impl_type(Executor const&, Args&&...);
|
||||
|
||||
template<class OtherProtocol>
|
||||
impl_type(net::basic_stream_socket<OtherProtocol>&& socket_,
|
||||
std::true_type);
|
||||
|
||||
template<class OtherProtocol>
|
||||
impl_type(net::basic_stream_socket<OtherProtocol>&& socket_,
|
||||
std::false_type);
|
||||
impl_type(Args&&...);
|
||||
|
||||
impl_type& operator=(impl_type&&) = delete;
|
||||
|
||||
Executor const&
|
||||
ex() const noexcept
|
||||
beast::executor_type<socket_type>
|
||||
ex() noexcept
|
||||
{
|
||||
return this->boost::empty_value<Executor>::get();
|
||||
return this->socket.get_executor();
|
||||
}
|
||||
|
||||
void reset(); // set timeouts to never
|
||||
@ -248,13 +263,6 @@ private:
|
||||
// but the implementation is still waiting on a timer.
|
||||
boost::shared_ptr<impl_type> impl_;
|
||||
|
||||
// Restricted until P1322R0 is incorporated into Boost.Asio.
|
||||
static_assert(
|
||||
std::is_convertible<
|
||||
decltype(std::declval<Executor const&>().context()),
|
||||
net::io_context&>::value,
|
||||
"Only net::io_context is currently supported for executor_type::context()");
|
||||
|
||||
template<bool, class, class> class async_op;
|
||||
|
||||
template<class, class, class>
|
||||
@ -287,22 +295,6 @@ private:
|
||||
#endif
|
||||
|
||||
public:
|
||||
/** The type of the executor associated with the stream.
|
||||
|
||||
This will be the type of executor used to invoke completion
|
||||
handlers which do not have an explicit associated executor.
|
||||
*/
|
||||
using executor_type = Executor;
|
||||
|
||||
/// The type of the underlying socket.
|
||||
using socket_type = net::basic_stream_socket<Protocol>;
|
||||
|
||||
/// The protocol type.
|
||||
using protocol_type = Protocol;
|
||||
|
||||
/// The endpoint type.
|
||||
using endpoint_type = typename Protocol::endpoint;
|
||||
|
||||
/** Destructor
|
||||
|
||||
This function destroys the stream, cancelling any outstanding
|
||||
@ -311,106 +303,20 @@ public:
|
||||
*/
|
||||
~basic_stream();
|
||||
|
||||
/** Construct the stream from an execution context.
|
||||
/** Constructor
|
||||
|
||||
This constructor creates the stream from an execution context.
|
||||
The underlying socket needs to be open and connected or accepted
|
||||
before data can be sent or received on it.
|
||||
|
||||
@param ctx An object whose type meets the requirements of
|
||||
<em>ExecutionContext</em>, which the stream will use to dispatch
|
||||
handlers that do not have an explicit associated executor.
|
||||
Currently, the only supported type for `ctx` is `net::io_context`.
|
||||
This constructor creates the stream by forwarding all arguments
|
||||
to the underlying socket. The socket then needs to be open and
|
||||
connected or accepted before data can be sent or received on it.
|
||||
|
||||
@param args A list of parameters forwarded to the constructor of
|
||||
the underlying socket.
|
||||
|
||||
@note This function does not participate in overload resolution unless:
|
||||
|
||||
@li `std::is_convertible<ExecutionContext&, net::execution_context&>::value` is `true`, and
|
||||
|
||||
@li `std::is_constructible<executor_type, typename ExecutionContext::executor_type>::value` is `true`.
|
||||
|
||||
@see <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1322r0.html">[P1322R0] Networking TS enhancement to enable custom I/O executors</a>
|
||||
*/
|
||||
template<
|
||||
class ExecutionContext,
|
||||
class... Args
|
||||
#if ! BOOST_BEAST_DOXYGEN
|
||||
, class = typename std::enable_if<
|
||||
std::is_convertible<
|
||||
ExecutionContext&,
|
||||
net::execution_context&>::value &&
|
||||
std::is_constructible<
|
||||
executor_type,
|
||||
typename ExecutionContext::executor_type>::value
|
||||
>::type
|
||||
#endif
|
||||
>
|
||||
explicit
|
||||
basic_stream(ExecutionContext& ctx, Args&&... args);
|
||||
|
||||
/** Construct the stream from an executor.
|
||||
|
||||
This constructor creates the stream from an executor.
|
||||
The underlying socket needs to be open and connected or accepted
|
||||
before data can be sent or received on it.
|
||||
|
||||
@param ex The executor to use when dispatching handlers that do
|
||||
not have an explicit associated executor.
|
||||
Currently, only executors that return a `net::io_context&` from
|
||||
`ex.context()` are supported.
|
||||
|
||||
@param args A list of parameters forwarded to the constructor of
|
||||
the underlying socket.
|
||||
|
||||
@see <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1322r0.html">[P1322R0] Networking TS enhancement to enable custom I/O executors</a>
|
||||
*/
|
||||
template<class... Args>
|
||||
explicit
|
||||
basic_stream(
|
||||
executor_type const& ex, Args&&... args);
|
||||
basic_stream(Args&&... args);
|
||||
|
||||
/** Construct the stream from an existing socket.
|
||||
|
||||
This constructor creates the stream from an existing socket.
|
||||
The underlying socket needs to be open and connected or accepted
|
||||
before data can be sent or received on it.
|
||||
|
||||
@param socket The socket to construct from. Ownership of the
|
||||
socket will be transferred by move-construction.
|
||||
|
||||
@param args A list of parameters forwarded to the constructor of
|
||||
the underlying socket.
|
||||
|
||||
@note This function does not participate in overload resolution unless:
|
||||
|
||||
@li `OtherProtocol` is convertible to `Protocol`, and one of:
|
||||
|
||||
@li `executor_type` of the stream is constructible from the type of
|
||||
context returned by calling `socket.get_executor().context()`, or
|
||||
|
||||
@li `executor_type` of the stream is constructible from the type of
|
||||
executor returned by calling `socket.get_executor()`.
|
||||
*/
|
||||
template<
|
||||
class OtherProtocol
|
||||
#if ! BOOST_BEAST_DOXYGEN
|
||||
,class = typename std::enable_if<
|
||||
std::is_convertible<OtherProtocol, Protocol>::value && (
|
||||
std::is_constructible<Executor,
|
||||
decltype(std::declval<net::basic_stream_socket<
|
||||
Protocol>&>().get_executor().context())>::value ||
|
||||
std::is_constructible<Executor,
|
||||
decltype(std::declval<net::basic_stream_socket<
|
||||
Protocol>&>().get_executor())>::value)
|
||||
>::type
|
||||
#endif
|
||||
>
|
||||
explicit
|
||||
basic_stream(net::basic_stream_socket<OtherProtocol>&& socket);
|
||||
|
||||
/** Move constructor.
|
||||
/** Move constructor
|
||||
|
||||
@param other The other object from which the move will occur.
|
||||
|
||||
|
107
include/boost/beast/core/detail/get_io_context.hpp
Normal file
107
include/boost/beast/core/detail/get_io_context.hpp
Normal file
@ -0,0 +1,107 @@
|
||||
//
|
||||
// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/beast
|
||||
//
|
||||
|
||||
#ifndef BOOST_BEAST_DETAIL_GET_IO_CONTEXT_HPP
|
||||
#define BOOST_BEAST_DETAIL_GET_IO_CONTEXT_HPP
|
||||
|
||||
#include <boost/beast/core/stream_traits.hpp>
|
||||
#include <boost/asio/executor.hpp>
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/asio/strand.hpp>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace detail {
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
inline
|
||||
net::io_context*
|
||||
get_io_context(net::io_context& ioc)
|
||||
{
|
||||
return std::addressof(ioc);
|
||||
}
|
||||
|
||||
inline
|
||||
net::io_context*
|
||||
get_io_context(net::io_context::executor_type const& ex)
|
||||
{
|
||||
return std::addressof(ex.context());
|
||||
}
|
||||
|
||||
inline
|
||||
net::io_context*
|
||||
get_io_context(net::strand<
|
||||
net::io_context::executor_type> const& ex)
|
||||
{
|
||||
return std::addressof(
|
||||
ex.get_inner_executor().context());
|
||||
}
|
||||
|
||||
template<class Executor>
|
||||
net::io_context*
|
||||
get_io_context(net::strand<Executor> const& ex)
|
||||
{
|
||||
return get_io_context(ex.get_inner_executor());
|
||||
}
|
||||
|
||||
template<
|
||||
class T,
|
||||
class = typename std::enable_if<
|
||||
std::is_same<T, net::executor>::value>::type>
|
||||
net::io_context*
|
||||
get_io_context(T const& ex)
|
||||
{
|
||||
auto p = ex.template target<typename
|
||||
net::io_context::executor_type>();
|
||||
if(! p)
|
||||
return nullptr;
|
||||
return std::addressof(p->context());
|
||||
}
|
||||
|
||||
inline
|
||||
net::io_context*
|
||||
get_io_context(...)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<class T>
|
||||
net::io_context*
|
||||
get_io_context_impl(T& t, std::true_type)
|
||||
{
|
||||
return get_io_context(
|
||||
t.get_executor());
|
||||
}
|
||||
|
||||
template<class T>
|
||||
net::io_context*
|
||||
get_io_context_impl(T const&, std::false_type)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Returns the io_context*, or nullptr, for any object.
|
||||
template<class T>
|
||||
net::io_context*
|
||||
get_io_context(T& t)
|
||||
{
|
||||
return get_io_context_impl(t,
|
||||
has_get_executor<T>{});
|
||||
}
|
||||
|
||||
} // detail
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
#endif
|
@ -15,6 +15,7 @@
|
||||
#include <boost/core/exchange.hpp>
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <utility>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
@ -48,9 +49,10 @@ struct stream_base
|
||||
bool pending = false; // if op is pending
|
||||
bool timeout = false; // if timed out
|
||||
|
||||
template<class... Args>
|
||||
explicit
|
||||
op_state(net::io_context& ioc)
|
||||
: timer(ioc)
|
||||
op_state(Args&&... args)
|
||||
: timer(std::forward<Args>(args)...)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
@ -32,44 +32,10 @@ template<class Protocol, class Executor>
|
||||
template<class... Args>
|
||||
basic_stream<Protocol, Executor>::
|
||||
impl_type::
|
||||
impl_type(
|
||||
Executor const& ex_,
|
||||
Args&&... args)
|
||||
: boost::empty_value<Executor>(
|
||||
boost::empty_init_t{}, ex_)
|
||||
, read(ex().context())
|
||||
, write(ex().context())
|
||||
, socket(std::forward<Args>(args)...)
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
template<class Protocol, class Executor>
|
||||
template<class OtherProtocol>
|
||||
basic_stream<Protocol, Executor>::
|
||||
impl_type::
|
||||
impl_type(net::basic_stream_socket<OtherProtocol>&& socket_,
|
||||
std::true_type)
|
||||
: boost::empty_value<Executor>(
|
||||
boost::empty_init_t{}, socket_.get_executor())
|
||||
, read(ex().context())
|
||||
, write(ex().context())
|
||||
, socket(std::move(socket_))
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
template<class Protocol, class Executor>
|
||||
template<class OtherProtocol>
|
||||
basic_stream<Protocol, Executor>::
|
||||
impl_type::
|
||||
impl_type(net::basic_stream_socket<OtherProtocol>&& socket_,
|
||||
std::false_type)
|
||||
: boost::empty_value<Executor>(boost::empty_init_t{},
|
||||
socket_.get_executor().context())
|
||||
, read(ex().context())
|
||||
, write(ex().context())
|
||||
, socket(std::move(socket_))
|
||||
impl_type(Args&&... args)
|
||||
: socket(std::forward<Args>(args)...)
|
||||
, read(ex())
|
||||
, write(ex())
|
||||
{
|
||||
reset();
|
||||
}
|
||||
@ -434,40 +400,12 @@ basic_stream<Protocol, Executor>::
|
||||
impl_->close();
|
||||
}
|
||||
|
||||
template<class Protocol, class Executor>
|
||||
template<class ExecutionContext, class... Args, class>
|
||||
basic_stream<Protocol, Executor>::
|
||||
basic_stream(ExecutionContext& ctx, Args&&... args)
|
||||
: impl_(boost::make_shared<impl_type>(
|
||||
ctx.get_executor(),
|
||||
ctx, std::forward<Args>(args)...))
|
||||
{
|
||||
// Restriction is necessary until Asio fully supports P1322R0
|
||||
static_assert(
|
||||
std::is_same<ExecutionContext, net::io_context>::value,
|
||||
"Only net::io_context is currently supported for ExecutionContext");
|
||||
}
|
||||
|
||||
template<class Protocol, class Executor>
|
||||
template<class... Args>
|
||||
basic_stream<Protocol, Executor>::
|
||||
basic_stream(
|
||||
executor_type const& ex, Args&&... args)
|
||||
basic_stream(Args&&... args)
|
||||
: impl_(boost::make_shared<impl_type>(
|
||||
ex,
|
||||
ex.context(), std::forward<Args>(args)...))
|
||||
{
|
||||
}
|
||||
|
||||
template<class Protocol, class Executor>
|
||||
template<class OtherProtocol, class>
|
||||
basic_stream<Protocol, Executor>::
|
||||
basic_stream(net::basic_stream_socket<OtherProtocol>&& socket)
|
||||
: impl_(boost::make_shared<impl_type>(
|
||||
std::move(socket),
|
||||
std::is_constructible<Executor,
|
||||
decltype(std::declval<net::basic_stream_socket<
|
||||
Protocol>&>().get_executor())>{}))
|
||||
std::forward<Args>(args)...))
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -438,10 +438,10 @@ using is_async_stream = std::integral_constant<bool,
|
||||
|
||||
@see close_socket
|
||||
*/
|
||||
template<class Protocol BOOST_ASIO_SVC_TPARAM>
|
||||
template<class Protocol>
|
||||
void
|
||||
beast_close_socket(
|
||||
net::basic_socket<Protocol BOOST_ASIO_SVC_TPARAM>& sock)
|
||||
net::basic_socket<Protocol>& sock)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
sock.close(ec);
|
||||
|
@ -12,20 +12,17 @@
|
||||
|
||||
#include <boost/beast/core/detail/config.hpp>
|
||||
#include <boost/beast/core/basic_stream.hpp>
|
||||
#include <boost/asio/executor.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
|
||||
/** A TCP/IP stream socket with timeouts, rate limits, and executor.
|
||||
|
||||
@tparam Executor The type of executor to use for all completion
|
||||
handlers which do not already have an associated executor.
|
||||
/** A TCP/IP stream socket with timeouts, rate limits, and polymorphic executor.
|
||||
|
||||
@see basic_stream
|
||||
*/
|
||||
template<class Executor>
|
||||
using tcp_stream = basic_stream<net::ip::tcp, Executor>;
|
||||
using tcp_stream = basic_stream<net::ip::tcp, net::executor>;
|
||||
|
||||
} // beast
|
||||
} // boost
|
||||
|
@ -30,6 +30,8 @@ using file_body = basic_file_body<file>;
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
#ifndef BOOST_BEAST_NO_FILE_BODY_WIN32
|
||||
#include <boost/beast/http/impl/file_body_win32.ipp>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -32,7 +32,7 @@ namespace beast {
|
||||
namespace http {
|
||||
|
||||
namespace detail {
|
||||
template<class, class, bool, class>
|
||||
template<class, class, class, bool, class>
|
||||
class write_some_win32_op;
|
||||
} // detail
|
||||
|
||||
@ -52,7 +52,7 @@ struct basic_file_body<file_win32>
|
||||
friend class reader;
|
||||
friend struct basic_file_body<file_win32>;
|
||||
|
||||
template<class, class, bool, class>
|
||||
template<class, class, class, bool, class>
|
||||
friend class detail::write_some_win32_op;
|
||||
template<
|
||||
class Protocol, bool isRequest, class Fields>
|
||||
@ -101,7 +101,7 @@ struct basic_file_body<file_win32>
|
||||
|
||||
class writer
|
||||
{
|
||||
template<class, class, bool, class>
|
||||
template<class, class, class, bool, class>
|
||||
friend class detail::write_some_win32_op;
|
||||
template<
|
||||
class Protocol, bool isRequest, class Fields>
|
||||
@ -276,7 +276,6 @@ reset(file_win32&& file, error_code& ec)
|
||||
namespace detail {
|
||||
|
||||
template<class Unsigned>
|
||||
inline
|
||||
boost::winapi::DWORD_
|
||||
lowPart(Unsigned n)
|
||||
{
|
||||
@ -286,7 +285,6 @@ lowPart(Unsigned n)
|
||||
}
|
||||
|
||||
template<class Unsigned>
|
||||
inline
|
||||
boost::winapi::DWORD_
|
||||
highPart(Unsigned n, std::true_type)
|
||||
{
|
||||
@ -296,7 +294,6 @@ highPart(Unsigned n, std::true_type)
|
||||
}
|
||||
|
||||
template<class Unsigned>
|
||||
inline
|
||||
boost::winapi::DWORD_
|
||||
highPart(Unsigned, std::false_type)
|
||||
{
|
||||
@ -304,7 +301,6 @@ highPart(Unsigned, std::false_type)
|
||||
}
|
||||
|
||||
template<class Unsigned>
|
||||
inline
|
||||
boost::winapi::DWORD_
|
||||
highPart(Unsigned n)
|
||||
{
|
||||
@ -329,14 +325,17 @@ public:
|
||||
#if BOOST_ASIO_HAS_WINDOWS_OVERLAPPED_PTR
|
||||
|
||||
template<
|
||||
class Protocol, class Handler,
|
||||
bool isRequest, class Fields>
|
||||
class Protocol, class Executor,
|
||||
class Handler, bool isRequest, class Fields>
|
||||
class write_some_win32_op
|
||||
: public beast::async_op_base<
|
||||
Handler, typename net::basic_stream_socket<
|
||||
Protocol>::executor_type>
|
||||
: public beast::async_op_base<Handler, Executor>
|
||||
{
|
||||
net::basic_stream_socket<Protocol>& sock_;
|
||||
static_assert(
|
||||
std::is_same<Executor, net::io_context::executor_type>::value,
|
||||
"Executor must be net::io_context::executor_type");
|
||||
|
||||
net::basic_stream_socket<
|
||||
Protocol, Executor>& sock_;
|
||||
serializer<isRequest,
|
||||
basic_file_body<file_win32>, Fields>& sr_;
|
||||
std::size_t bytes_transferred_ = 0;
|
||||
@ -346,14 +345,14 @@ public:
|
||||
template<class Handler_>
|
||||
write_some_win32_op(
|
||||
Handler_&& h,
|
||||
net::basic_stream_socket<Protocol>& s,
|
||||
net::basic_stream_socket<
|
||||
Protocol, Executor>& s,
|
||||
serializer<isRequest,
|
||||
basic_file_body<file_win32>,Fields>& sr)
|
||||
: async_op_base<
|
||||
Handler, typename net::basic_stream_socket<
|
||||
Protocol>::executor_type>(
|
||||
std::forward<Handler_>(h),
|
||||
s.get_executor())
|
||||
Handler, Executor>(
|
||||
std::forward<Handler_>(h),
|
||||
s.get_executor())
|
||||
, sock_(s)
|
||||
, sr_(sr)
|
||||
{
|
||||
@ -442,10 +441,13 @@ public:
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<class Protocol, bool isRequest, class Fields>
|
||||
template<
|
||||
class Protocol, class Executor,
|
||||
bool isRequest, class Fields>
|
||||
std::size_t
|
||||
write_some(
|
||||
net::basic_stream_socket<Protocol>& sock,
|
||||
net::basic_stream_socket<
|
||||
Protocol, Executor>& sock,
|
||||
serializer<isRequest,
|
||||
basic_file_body<file_win32>, Fields>& sr,
|
||||
error_code& ec)
|
||||
@ -509,21 +511,23 @@ write_some(
|
||||
#if BOOST_ASIO_HAS_WINDOWS_OVERLAPPED_PTR
|
||||
|
||||
template<
|
||||
class Protocol,
|
||||
class Protocol, class Executor,
|
||||
bool isRequest, class Fields,
|
||||
class WriteHandler>
|
||||
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||
WriteHandler, void(error_code, std::size_t))
|
||||
async_write_some(
|
||||
net::basic_stream_socket<Protocol>& sock,
|
||||
net::basic_stream_socket<
|
||||
Protocol, Executor>& sock,
|
||||
serializer<isRequest,
|
||||
basic_file_body<file_win32>, Fields>& sr,
|
||||
WriteHandler&& handler)
|
||||
{
|
||||
|
||||
BOOST_BEAST_HANDLER_INIT(
|
||||
WriteHandler, void(error_code, std::size_t));
|
||||
detail::write_some_win32_op<
|
||||
Protocol,
|
||||
Protocol, Executor,
|
||||
BOOST_ASIO_HANDLER_TYPE(WriteHandler,
|
||||
void(error_code, std::size_t)),
|
||||
isRequest, Fields>{
|
||||
|
@ -19,7 +19,15 @@
|
||||
#include <boost/beast/core/static_string.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
// This is for <boost/endian/buffers.hpp>
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, > 0)
|
||||
# pragma warning (push)
|
||||
# pragma warning (disable: 4127) // conditional expression is constant
|
||||
#endif
|
||||
#include <boost/endian/buffers.hpp>
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, > 0)
|
||||
# pragma warning (pop)
|
||||
#endif
|
||||
#include <cstdint>
|
||||
|
||||
namespace boost {
|
||||
|
@ -103,7 +103,7 @@ struct stream<NextLayer, deflateSupported>::impl_type
|
||||
template<class... Args>
|
||||
impl_type(Args&&... args)
|
||||
: stream(std::forward<Args>(args)...)
|
||||
, timer(stream.get_executor().context())
|
||||
, timer(stream.get_executor())
|
||||
{
|
||||
timeout_opt.handshake_timeout = none();
|
||||
timeout_opt.idle_timeout = none();
|
||||
|
@ -25,14 +25,18 @@ namespace websocket {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<class Handler>
|
||||
template<
|
||||
class Protocol, class Executor,
|
||||
class Handler>
|
||||
class teardown_tcp_op
|
||||
: public beast::async_op_base<
|
||||
Handler, beast::executor_type<
|
||||
net::ip::tcp::socket>>
|
||||
net::basic_stream_socket<
|
||||
Protocol, Executor>>>
|
||||
, public net::coroutine
|
||||
{
|
||||
using socket_type = net::ip::tcp::socket;
|
||||
using socket_type =
|
||||
net::basic_stream_socket<Protocol, Executor>;
|
||||
|
||||
socket_type& s_;
|
||||
role_type role_;
|
||||
@ -46,8 +50,10 @@ public:
|
||||
role_type role)
|
||||
: async_op_base<Handler,
|
||||
beast::executor_type<
|
||||
net::ip::tcp::socket>>(
|
||||
std::forward<Handler_>(h), s.get_executor())
|
||||
net::basic_stream_socket<
|
||||
Protocol, Executor>>>(
|
||||
std::forward<Handler_>(h),
|
||||
s.get_executor())
|
||||
, s_(s)
|
||||
, role_(role)
|
||||
{
|
||||
@ -60,7 +66,6 @@ public:
|
||||
std::size_t bytes_transferred = 0,
|
||||
bool cont = true)
|
||||
{
|
||||
using tcp = net::ip::tcp;
|
||||
BOOST_ASIO_CORO_REENTER(*this)
|
||||
{
|
||||
nb_ = s_.non_blocking();
|
||||
@ -68,7 +73,7 @@ public:
|
||||
if(ec)
|
||||
goto upcall;
|
||||
if(role_ == role_type::server)
|
||||
s_.shutdown(tcp::socket::shutdown_send, ec);
|
||||
s_.shutdown(net::socket_base::shutdown_send, ec);
|
||||
if(ec)
|
||||
goto upcall;
|
||||
for(;;)
|
||||
@ -81,7 +86,7 @@ public:
|
||||
{
|
||||
BOOST_ASIO_CORO_YIELD
|
||||
s_.async_wait(
|
||||
net::ip::tcp::socket::wait_read,
|
||||
net::socket_base::wait_read,
|
||||
beast::detail::bind_continuation(std::move(*this)));
|
||||
continue;
|
||||
}
|
||||
@ -100,7 +105,7 @@ public:
|
||||
}
|
||||
}
|
||||
if(role_ == role_type::client)
|
||||
s_.shutdown(tcp::socket::shutdown_send, ec);
|
||||
s_.shutdown(net::socket_base::shutdown_send, ec);
|
||||
if(ec)
|
||||
goto upcall;
|
||||
s_.close(ec);
|
||||
@ -124,15 +129,17 @@ public:
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<class Protocol, class Executor>
|
||||
void
|
||||
teardown(
|
||||
role_type role,
|
||||
net::ip::tcp::socket& socket,
|
||||
net::basic_stream_socket<
|
||||
Protocol, Executor>& socket,
|
||||
error_code& ec)
|
||||
{
|
||||
if(role == role_type::server)
|
||||
socket.shutdown(
|
||||
net::ip::tcp::socket::shutdown_send, ec);
|
||||
net::socket_base::shutdown_send, ec);
|
||||
if(ec)
|
||||
return;
|
||||
for(;;)
|
||||
@ -156,25 +163,32 @@ teardown(
|
||||
}
|
||||
if(role == role_type::client)
|
||||
socket.shutdown(
|
||||
net::ip::tcp::socket::shutdown_send, ec);
|
||||
net::socket_base::shutdown_send, ec);
|
||||
if(ec)
|
||||
return;
|
||||
socket.close(ec);
|
||||
}
|
||||
|
||||
template<class TeardownHandler>
|
||||
template<
|
||||
class Protocol, class Executor,
|
||||
class TeardownHandler>
|
||||
void
|
||||
async_teardown(
|
||||
role_type role,
|
||||
net::ip::tcp::socket& socket,
|
||||
net::basic_stream_socket<
|
||||
Protocol, Executor>& socket,
|
||||
TeardownHandler&& handler)
|
||||
{
|
||||
static_assert(beast::detail::is_invocable<
|
||||
TeardownHandler, void(error_code)>::value,
|
||||
"TeardownHandler requirements not met");
|
||||
detail::teardown_tcp_op<typename std::decay<
|
||||
TeardownHandler>::type>(std::forward<
|
||||
TeardownHandler>(handler), socket, role);
|
||||
detail::teardown_tcp_op<
|
||||
Protocol,
|
||||
Executor,
|
||||
typename std::decay<TeardownHandler>::type>(
|
||||
std::forward<TeardownHandler>(handler),
|
||||
socket,
|
||||
role);
|
||||
}
|
||||
|
||||
} // websocket
|
||||
|
@ -80,13 +80,12 @@ class frame_test;
|
||||
To declare the @ref stream object with a @ref tcp_stream in a
|
||||
multi-threaded asynchronous program using a strand, you may write:
|
||||
@code
|
||||
websocket::stream<tcp_stream<
|
||||
net::io_context::strand>> ws{net::io_context::strand(ioc)};
|
||||
websocket::stream<tcp_stream> ws{net::io_context::strand(ioc)};
|
||||
@endcode
|
||||
Alternatively, for a single-threaded or synchronous application
|
||||
you may write:
|
||||
@code
|
||||
websocket::stream<tcp_stream<net::io_context::executor_type>> ws(ioc);
|
||||
websocket::stream<tcp_stream> ws(ioc);
|
||||
@endcode
|
||||
|
||||
@tparam NextLayer The type representing the next layer, to which
|
||||
|
@ -13,7 +13,7 @@
|
||||
#include <boost/beast/core/detail/config.hpp>
|
||||
#include <boost/beast/core/error.hpp>
|
||||
#include <boost/beast/websocket/role.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/asio/basic_stream_socket.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
@ -125,11 +125,12 @@ namespace websocket {
|
||||
|
||||
@param ec Set to the error if any occurred.
|
||||
*/
|
||||
BOOST_BEAST_DECL
|
||||
template<class Protocol, class Executor>
|
||||
void
|
||||
teardown(
|
||||
role_type role,
|
||||
net::ip::tcp::socket& socket,
|
||||
net::basic_stream_socket<
|
||||
Protocol, Executor>& socket,
|
||||
error_code& ec);
|
||||
|
||||
/** Start tearing down a `net::ip::tcp::socket`.
|
||||
@ -159,11 +160,14 @@ teardown(
|
||||
manner equivalent to using net::io_context::post().
|
||||
|
||||
*/
|
||||
template<class TeardownHandler>
|
||||
template<
|
||||
class Protocol, class Executor,
|
||||
class TeardownHandler>
|
||||
void
|
||||
async_teardown(
|
||||
role_type role,
|
||||
net::ip::tcp::socket& socket,
|
||||
net::basic_stream_socket<
|
||||
Protocol, Executor>& socket,
|
||||
TeardownHandler&& handler);
|
||||
|
||||
} // websocket
|
||||
|
@ -24,6 +24,7 @@ add_executable (tests-beast-core
|
||||
_detail_bind_continuation.cpp
|
||||
_detail_buffer.cpp
|
||||
_detail_clamp.cpp
|
||||
_detail_get_io_context.cpp
|
||||
_detail_is_invocable.cpp
|
||||
_detail_read.cpp
|
||||
_detail_sha1.cpp
|
||||
|
@ -12,6 +12,7 @@ local SOURCES =
|
||||
_detail_bind_continuation.cpp
|
||||
_detail_buffer.cpp
|
||||
_detail_clamp.cpp
|
||||
_detail_get_io_context.cpp
|
||||
_detail_is_invocable.cpp
|
||||
_detail_read.cpp
|
||||
_detail_sha1.cpp
|
||||
|
57
test/beast/core/_detail_get_io_context.cpp
Normal file
57
test/beast/core/_detail_get_io_context.cpp
Normal file
@ -0,0 +1,57 @@
|
||||
//
|
||||
// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/beast
|
||||
//
|
||||
|
||||
#include <boost/beast/core/detail/config.hpp>
|
||||
#include <boost/beast/core/make_strand.hpp>
|
||||
#include <boost/beast/core/detail/get_io_context.hpp>
|
||||
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
||||
#include <boost/asio/strand.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace detail {
|
||||
|
||||
class get_io_context_test : public beast::unit_test::suite
|
||||
{
|
||||
public:
|
||||
void
|
||||
testFunction()
|
||||
{
|
||||
struct none
|
||||
{
|
||||
};
|
||||
|
||||
net::io_context ioc;
|
||||
BEAST_EXPECT(get_io_context(5) == nullptr);
|
||||
BEAST_EXPECT(get_io_context(none{}) == nullptr);
|
||||
BEAST_EXPECT(get_io_context(ioc) == &ioc);
|
||||
BEAST_EXPECT(get_io_context(ioc.get_executor()) == &ioc);
|
||||
BEAST_EXPECT(get_io_context(make_strand(ioc)) == &ioc);
|
||||
BEAST_EXPECT(get_io_context(net::executor(ioc.get_executor())) == &ioc);
|
||||
#if 0
|
||||
// VFALCO FIXME
|
||||
BEAST_EXPECT(
|
||||
get_io_context(
|
||||
net::strand<net::executor>(
|
||||
net::executor(ioc.get_executor()))) == &ioc);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
run() override
|
||||
{
|
||||
testFunction();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(beast,core,get_io_context);
|
||||
|
||||
} // detail
|
||||
} // beast
|
||||
} // boost
|
@ -303,7 +303,6 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // (anon)
|
||||
|
||||
class basic_stream_test
|
||||
@ -319,9 +318,6 @@ public:
|
||||
void
|
||||
testSpecialMembers()
|
||||
{
|
||||
using stream_type = tcp_stream<
|
||||
net::io_context::executor_type>;
|
||||
|
||||
net::io_context ioc;
|
||||
|
||||
// net::io_context::executor_type
|
||||
@ -332,7 +328,8 @@ public:
|
||||
basic_stream<tcp, executor> s2(ex);
|
||||
basic_stream<tcp, executor> s3(ioc, tcp::v4());
|
||||
basic_stream<tcp, executor> s4(std::move(s1));
|
||||
s2.socket() = tcp::socket(ioc);
|
||||
s2.socket() =
|
||||
net::basic_stream_socket<tcp, executor>(ioc);
|
||||
BEAST_EXPECT(s1.get_executor() == ex);
|
||||
BEAST_EXPECT(s2.get_executor() == ex);
|
||||
BEAST_EXPECT(s3.get_executor() == ex);
|
||||
@ -358,14 +355,19 @@ public:
|
||||
basic_stream<tcp, strand> s1(ex);
|
||||
basic_stream<tcp, strand> s2(ex, tcp::v4());
|
||||
basic_stream<tcp, strand> s3(std::move(s1));
|
||||
s2.socket() = tcp::socket(ioc);
|
||||
#if 0
|
||||
s2.socket() = net::basic_stream_socket<
|
||||
tcp, strand>(ioc);
|
||||
#endif
|
||||
BEAST_EXPECT(s1.get_executor() == ex);
|
||||
BEAST_EXPECT(s2.get_executor() == ex);
|
||||
BEAST_EXPECT(s3.get_executor() == ex);
|
||||
|
||||
#if 0
|
||||
BEAST_EXPECT((! static_cast<
|
||||
basic_stream<tcp, strand> const&>(
|
||||
s2).socket().is_open()));
|
||||
#endif
|
||||
|
||||
test_sync_stream<
|
||||
basic_stream<
|
||||
@ -378,6 +380,7 @@ public:
|
||||
|
||||
// construction from existing socket
|
||||
|
||||
#if 0
|
||||
{
|
||||
tcp::socket sock(ioc);
|
||||
basic_stream<tcp, executor> stream(std::move(sock));
|
||||
@ -387,22 +390,13 @@ public:
|
||||
tcp::socket sock(ioc);
|
||||
basic_stream<tcp, strand> stream(std::move(sock));
|
||||
}
|
||||
|
||||
struct other_type
|
||||
{
|
||||
};
|
||||
|
||||
BOOST_STATIC_ASSERT(! std::is_constructible<
|
||||
stream_type, other_type>::value);
|
||||
|
||||
BOOST_STATIC_ASSERT(! std::is_constructible<
|
||||
stream_type, other_type, tcp::socket>::value);
|
||||
#endif
|
||||
|
||||
// layers
|
||||
|
||||
{
|
||||
net::socket_base::keep_alive opt;
|
||||
stream_type s(ioc);
|
||||
tcp_stream s(ioc);
|
||||
s.socket().open(tcp::v4());
|
||||
s.socket().get_option(opt);
|
||||
BEAST_EXPECT(! opt.value());
|
||||
@ -450,7 +444,7 @@ public:
|
||||
void
|
||||
testRead()
|
||||
{
|
||||
using stream_type = tcp_stream<
|
||||
using stream_type = basic_stream<tcp,
|
||||
net::io_context::executor_type>;
|
||||
|
||||
char buf[4];
|
||||
@ -585,7 +579,7 @@ public:
|
||||
void
|
||||
testWrite()
|
||||
{
|
||||
using stream_type = tcp_stream<
|
||||
using stream_type = basic_stream<tcp,
|
||||
net::io_context::executor_type>;
|
||||
|
||||
char buf[4];
|
||||
@ -667,7 +661,7 @@ public:
|
||||
void
|
||||
testConnect()
|
||||
{
|
||||
using stream_type = tcp_stream<
|
||||
using stream_type = basic_stream<tcp,
|
||||
net::io_context::executor_type>;
|
||||
|
||||
struct range
|
||||
@ -1057,7 +1051,7 @@ public:
|
||||
void
|
||||
testMembers()
|
||||
{
|
||||
using stream_type = tcp_stream<
|
||||
using stream_type = basic_stream<tcp,
|
||||
net::io_context::executor_type>;
|
||||
|
||||
class handler
|
||||
@ -1184,7 +1178,7 @@ public:
|
||||
return {};
|
||||
}
|
||||
|
||||
void process_http_1 (tcp_stream<net::io_context::executor_type>& stream, net::yield_context yield)
|
||||
void process_http_1 (tcp_stream& stream, net::yield_context yield)
|
||||
{
|
||||
flat_buffer buffer;
|
||||
http::request<http::empty_body> req;
|
||||
@ -1201,7 +1195,7 @@ public:
|
||||
http::async_write (stream, res, yield);
|
||||
}
|
||||
|
||||
void process_http_2 (tcp_stream<net::io_context::executor_type>& stream, net::yield_context yield)
|
||||
void process_http_2 (tcp_stream& stream, net::yield_context yield)
|
||||
{
|
||||
flat_buffer buffer;
|
||||
http::request<http::empty_body> req;
|
||||
|
@ -9,3 +9,37 @@
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include <boost/beast/core/tcp_stream.hpp>
|
||||
|
||||
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
|
||||
class tcp_stream_test
|
||||
: public beast::unit_test::suite
|
||||
{
|
||||
public:
|
||||
using tcp = net::ip::tcp;
|
||||
|
||||
void
|
||||
testStream()
|
||||
{
|
||||
net::io_context ioc;
|
||||
{
|
||||
tcp::socket s(ioc);
|
||||
tcp_stream s1(std::move(s));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
run()
|
||||
{
|
||||
testStream();
|
||||
pass();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(beast,core,tcp_stream);
|
||||
|
||||
} // beast
|
||||
} // boost
|
||||
|
@ -10,6 +10,7 @@
|
||||
// Test that header file is self-contained.
|
||||
#include <boost/beast/websocket/stream.hpp>
|
||||
|
||||
#include <boost/beast/core/make_strand.hpp>
|
||||
#include <boost/beast/core/tcp_stream.hpp>
|
||||
#include <boost/asio/strand.hpp>
|
||||
|
||||
@ -157,11 +158,10 @@ public:
|
||||
{
|
||||
net::io_context ioc;
|
||||
{
|
||||
websocket::stream<tcp_stream<
|
||||
net::io_context::strand>> ws{net::io_context::strand(ioc)};
|
||||
websocket::stream<tcp_stream> ws{make_strand(ioc)};
|
||||
}
|
||||
{
|
||||
websocket::stream<tcp_stream<net::io_context::executor_type>> ws(ioc);
|
||||
websocket::stream<tcp_stream> ws(ioc);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,6 +28,7 @@ public:
|
||||
run() override
|
||||
{
|
||||
testJavadoc();
|
||||
pass();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -59,8 +59,8 @@ boost::ignore_unused(ec);
|
||||
{
|
||||
//[ws_snippet_6
|
||||
std::string const host = "example.com";
|
||||
net::ip::tcp::resolver r{ioc};
|
||||
stream<tcp_stream<net::io_context::executor_type>> ws{ioc};
|
||||
net::ip::tcp::resolver r(ioc);
|
||||
stream<tcp_stream> ws(ioc);
|
||||
auto const results = r.resolve(host, "ws");
|
||||
connect(get_lowest_layer(ws), results.begin(), results.end());
|
||||
//]
|
||||
@ -69,7 +69,7 @@ boost::ignore_unused(ec);
|
||||
{
|
||||
//[ws_snippet_7
|
||||
net::ip::tcp::acceptor acceptor{ioc};
|
||||
stream<tcp_stream<net::io_context::executor_type>> ws{acceptor.get_executor().context()};
|
||||
stream<tcp_stream> ws{acceptor.get_executor()};
|
||||
acceptor.accept(get_lowest_layer(ws).socket());
|
||||
//]
|
||||
}
|
||||
|
Reference in New Issue
Block a user