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:
Vinnie Falco committed 2019-02-19 16:23:30 -08:00
1 parent ac24e58fb3
commit 6baa607295
58 files changed
+762 -723

No files matched your search

+16 -13
View File
@@ -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());
+44 -138
View File
@@ -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.
@@ -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)...)
{
}
};
+6 -68
View File
@@ -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)...))
{
}
+2 -2
View File
@@ -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);
+3 -6
View File
@@ -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
+2
View File
@@ -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();
+31 -17
View File
@@ -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
+2 -3
View File
@@ -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
+9 -5
View File
@@ -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