mirror of
https://github.com/boostorg/beast.git
synced 2025-08-02 14:24:31 +02:00
Add close_socket, beast_close_socket customization:
This algorithm allows a socket-like object to be closed in a generic context. The customization point enables user-defined types to define the close algorithm to use with `close_socket`.
This commit is contained in:
@@ -2,6 +2,7 @@ Version 208:
|
|||||||
|
|
||||||
* Add get_lowest_layer free function
|
* Add get_lowest_layer free function
|
||||||
* Add lowest_layer_type metafunction
|
* Add lowest_layer_type metafunction
|
||||||
|
* Add close_socket, beast_close_socket customization
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@@ -60,6 +60,15 @@ facilities for authoring and working with layered streams:
|
|||||||
read and write streams, and additionally implements configurable buffering
|
read and write streams, and additionally implements configurable buffering
|
||||||
for reads.
|
for reads.
|
||||||
]]
|
]]
|
||||||
|
[[
|
||||||
|
[link beast.ref.boost__beast__close_socket `close_socket`]
|
||||||
|
][
|
||||||
|
This function closes a socket by performing an unqualified call
|
||||||
|
to the
|
||||||
|
[link beast.ref.boost__beast__beast_close_socket `beast_close_socket`]
|
||||||
|
customization point, allowing sockets to be closed in generic
|
||||||
|
contexts in an extensible fashion.
|
||||||
|
]]
|
||||||
[[
|
[[
|
||||||
[link beast.ref.boost__beast__flat_stream `flat_stream`]
|
[link beast.ref.boost__beast__flat_stream `flat_stream`]
|
||||||
][
|
][
|
||||||
@@ -67,20 +76,6 @@ facilities for authoring and working with layered streams:
|
|||||||
a limitation of `net::ssl::stream`. It is used in the implementation
|
a limitation of `net::ssl::stream`. It is used in the implementation
|
||||||
of [link beast.ref.boost__beast__ssl_stream `ssl_stream`].
|
of [link beast.ref.boost__beast__ssl_stream `ssl_stream`].
|
||||||
]]
|
]]
|
||||||
[[
|
|
||||||
[link beast.ref.boost__beast__http__icy_stream `http::icy_stream`]
|
|
||||||
][
|
|
||||||
An ICY stream transparently converts the non-standard "ICY 200 OK"
|
|
||||||
HTTP response from Shoutcast servers into a conforming 200 level
|
|
||||||
HTTP response.
|
|
||||||
]]
|
|
||||||
[[
|
|
||||||
[link beast.ref.boost__beast__ssl_stream `ssl_stream`]
|
|
||||||
][
|
|
||||||
The SSL stream is a drop-in replacement for `net::ssl::stream` which
|
|
||||||
allows for move-construction and move-assignment, and also implements
|
|
||||||
a work-around for a performance limitation in the original SSL stream.
|
|
||||||
]]
|
|
||||||
[[
|
[[
|
||||||
[link beast.ref.boost__beast__get_lowest_layer `get_lowest_layer`]
|
[link beast.ref.boost__beast__get_lowest_layer `get_lowest_layer`]
|
||||||
][
|
][
|
||||||
@@ -92,6 +87,13 @@ facilities for authoring and working with layered streams:
|
|||||||
|
|
||||||
[code_core_3_layers_4]
|
[code_core_3_layers_4]
|
||||||
]]
|
]]
|
||||||
|
[[
|
||||||
|
[link beast.ref.boost__beast__http__icy_stream `http::icy_stream`]
|
||||||
|
][
|
||||||
|
An ICY stream transparently converts the non-standard "ICY 200 OK"
|
||||||
|
HTTP response from Shoutcast servers into a conforming 200 level
|
||||||
|
HTTP response.
|
||||||
|
]]
|
||||||
[[
|
[[
|
||||||
[link beast.ref.boost__beast__lowest_layer_type `lowest_layer_type`]
|
[link beast.ref.boost__beast__lowest_layer_type `lowest_layer_type`]
|
||||||
][
|
][
|
||||||
@@ -100,6 +102,13 @@ facilities for authoring and working with layered streams:
|
|||||||
of reference returned by
|
of reference returned by
|
||||||
[link beast.ref.boost__beast__get_lowest_layer `get_lowest_layer`]
|
[link beast.ref.boost__beast__get_lowest_layer `get_lowest_layer`]
|
||||||
]]
|
]]
|
||||||
|
[[
|
||||||
|
[link beast.ref.boost__beast__ssl_stream `ssl_stream`]
|
||||||
|
][
|
||||||
|
The SSL stream is a drop-in replacement for `net::ssl::stream` which
|
||||||
|
allows for move-construction and move-assignment, and also implements
|
||||||
|
a work-around for a performance limitation in the original SSL stream.
|
||||||
|
]]
|
||||||
]
|
]
|
||||||
|
|
||||||
[heading Example]
|
[heading Example]
|
||||||
|
@@ -225,6 +225,7 @@
|
|||||||
<simplelist type="vert" columns="1">
|
<simplelist type="vert" columns="1">
|
||||||
<member><link linkend="beast.ref.boost__beast__allocate_stable">allocate_stable</link></member>
|
<member><link linkend="beast.ref.boost__beast__allocate_stable">allocate_stable</link></member>
|
||||||
<member><link linkend="beast.ref.boost__beast__async_connect">async_connect</link></member>
|
<member><link linkend="beast.ref.boost__beast__async_connect">async_connect</link></member>
|
||||||
|
<member><link linkend="beast.ref.boost__beast__beast_close_socket">beast_close_socket</link></member>
|
||||||
<member><link linkend="beast.ref.boost__beast__bind_back_handler">bind_back_handler</link></member>
|
<member><link linkend="beast.ref.boost__beast__bind_back_handler">bind_back_handler</link></member>
|
||||||
<member><link linkend="beast.ref.boost__beast__bind_front_handler">bind_front_handler</link></member>
|
<member><link linkend="beast.ref.boost__beast__bind_front_handler">bind_front_handler</link></member>
|
||||||
<member><link linkend="beast.ref.boost__beast__bind_handler">bind_handler</link></member>
|
<member><link linkend="beast.ref.boost__beast__bind_handler">bind_handler</link></member>
|
||||||
|
@@ -504,6 +504,15 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if ! BOOST_BEAST_DOXYGEN
|
||||||
|
inline
|
||||||
|
void
|
||||||
|
beast_close_socket(stream& s)
|
||||||
|
{
|
||||||
|
s.close();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if BOOST_BEAST_DOXYGEN
|
#if BOOST_BEAST_DOXYGEN
|
||||||
/** Return a new stream connected to the given stream
|
/** Return a new stream connected to the given stream
|
||||||
|
|
||||||
|
@@ -11,35 +11,121 @@
|
|||||||
#define BOOST_BEAST_CLOSE_SOCKET_HPP
|
#define BOOST_BEAST_CLOSE_SOCKET_HPP
|
||||||
|
|
||||||
#include <boost/beast/core/detail/config.hpp>
|
#include <boost/beast/core/detail/config.hpp>
|
||||||
|
#include <boost/beast/core/detail/static_const.hpp>
|
||||||
#include <boost/asio/basic_socket.hpp>
|
#include <boost/asio/basic_socket.hpp>
|
||||||
|
|
||||||
namespace boost {
|
namespace boost {
|
||||||
namespace beast {
|
namespace beast {
|
||||||
|
|
||||||
namespace detail {
|
/** Default socket close function.
|
||||||
|
|
||||||
template<class Protocol>
|
This function is not meant to be called directly. Instead, it
|
||||||
|
is called automatically when using @ref close_socket. To enable
|
||||||
|
closure of user-defined types or classes derived from a particular
|
||||||
|
user-defined type, this function should be overloaded in the
|
||||||
|
corresponding namespace for the type in question.
|
||||||
|
|
||||||
|
@see close_socket
|
||||||
|
*/
|
||||||
|
template<class Protocol BOOST_ASIO_SVC_TPARAM>
|
||||||
void
|
void
|
||||||
beast_close_socket(
|
beast_close_socket(
|
||||||
net::basic_socket<Protocol>& sock)
|
net::basic_socket<Protocol BOOST_ASIO_SVC_TPARAM>& sock)
|
||||||
{
|
{
|
||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
sock.close(ec);
|
sock.close(ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
struct close_socket_impl
|
||||||
|
{
|
||||||
|
template<class T>
|
||||||
|
void
|
||||||
|
operator()(T& t) const
|
||||||
|
{
|
||||||
|
using beast::beast_close_socket;
|
||||||
|
beast_close_socket(t);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} // detail
|
} // detail
|
||||||
|
|
||||||
/** Close a socket.
|
/** Close a socket or socket-like object.
|
||||||
|
|
||||||
@param sock The socket to close.
|
This function attempts to close an object representing a socket.
|
||||||
|
In this context, a socket is an object for which an unqualified
|
||||||
|
call to the function `void beast_close_socket(Socket&)` is
|
||||||
|
well-defined. The function `beast_close_socket` is a
|
||||||
|
<em>customization point</em>, allowing user-defined types to
|
||||||
|
provide an algorithm for performing the close operation by
|
||||||
|
overloading this function for the type in question.
|
||||||
|
|
||||||
|
Since the customization point is a function call, the normal
|
||||||
|
rules for finding the correct overload are applied including
|
||||||
|
the rules for argument-dependent lookup ("ADL"). This permits
|
||||||
|
classes derived from a type for which a customization is provided
|
||||||
|
to inherit the customization point.
|
||||||
|
|
||||||
|
An overload for the networking class template `net::basic_socket`
|
||||||
|
is provided, which implements the close algorithm for all socket-like
|
||||||
|
objects (hence the name of this customization point). When used
|
||||||
|
in conjunction with @ref get_lowest_layer, a generic algorithm
|
||||||
|
operating on a layered stream can perform a closure of the underlying
|
||||||
|
socket without knowing the exact list of concrete types.
|
||||||
|
|
||||||
|
@par Example 1
|
||||||
|
The following generic function synchronously sends a message
|
||||||
|
on the stream, then closes the socket.
|
||||||
|
@code
|
||||||
|
template <class WriteStream>
|
||||||
|
void hello_and_close (WriteStream& stream)
|
||||||
|
{
|
||||||
|
net::write(stream, net::const_buffer("Hello, world!", 13));
|
||||||
|
close_socket(get_lowest_layer(stream));
|
||||||
|
}
|
||||||
|
@endcode
|
||||||
|
|
||||||
|
To enable closure of user defined types, it is necessary to provide
|
||||||
|
an overload of the function `beast_close_socket` for the type.
|
||||||
|
|
||||||
|
@par Example 2
|
||||||
|
The following code declares a user-defined type which contains a
|
||||||
|
private socket, and provides an overload of the customization
|
||||||
|
point which closes the private socket.
|
||||||
|
@code
|
||||||
|
class my_socket
|
||||||
|
{
|
||||||
|
net::ip::tcp::socket sock_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
my_socket(net::io_context& ioc)
|
||||||
|
: sock_(ioc)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
friend void beast_close_socket(my_socket& s)
|
||||||
|
{
|
||||||
|
error_code ec;
|
||||||
|
s.sock_.close(ec);
|
||||||
|
// ignore the error
|
||||||
|
}
|
||||||
|
};
|
||||||
|
@endcode
|
||||||
|
|
||||||
|
@param sock The socket to close. If the customization point is not
|
||||||
|
defined for the type of this object, or one of its base classes,
|
||||||
|
then a compiler error results.
|
||||||
|
|
||||||
|
@see beast_close_socket
|
||||||
*/
|
*/
|
||||||
|
#if BOOST_BEAST_DOXYGEN
|
||||||
template<class Socket>
|
template<class Socket>
|
||||||
void
|
void
|
||||||
close_socket(Socket& sock)
|
close_socket(Socket& sock);
|
||||||
{
|
#else
|
||||||
using detail::beast_close_socket;
|
BOOST_BEAST_INLINE_VARIABLE(close_socket, detail::close_socket_impl)
|
||||||
beast_close_socket(sock);
|
#endif
|
||||||
}
|
|
||||||
|
|
||||||
} // beast
|
} // beast
|
||||||
} // boost
|
} // boost
|
||||||
|
@@ -73,4 +73,11 @@ namespace net = boost::asio;
|
|||||||
# define BOOST_BEAST_DECL inline
|
# define BOOST_BEAST_DECL inline
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define BOOST_BEAST_INLINE_VARIABLE(name, type) \
|
||||||
|
inline namespace \
|
||||||
|
{ \
|
||||||
|
constexpr auto &name = \
|
||||||
|
::boost::beast::detail::static_const<type>::value; \
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -17,46 +17,38 @@ namespace boost {
|
|||||||
namespace beast {
|
namespace beast {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
template<class T, class = void>
|
template <class T>
|
||||||
struct has_next_layer : std::false_type
|
std::false_type has_next_layer_impl(void*) {}
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class T>
|
template <class T>
|
||||||
struct has_next_layer<T, boost::void_t<
|
auto has_next_layer_impl(decltype(nullptr)) ->
|
||||||
decltype(std::declval<T>().next_layer())>>
|
decltype(std::declval<T&>().next_layer(), std::true_type{})
|
||||||
: std::true_type
|
|
||||||
{
|
{
|
||||||
};
|
}
|
||||||
|
|
||||||
template<class T, class = void>
|
template <class T>
|
||||||
|
using has_next_layer = decltype(has_next_layer_impl<T>(nullptr));
|
||||||
|
|
||||||
|
//---
|
||||||
|
|
||||||
|
template<class T, bool = has_next_layer<T>::value>
|
||||||
struct lowest_layer_type_impl
|
struct lowest_layer_type_impl
|
||||||
{
|
{
|
||||||
using type = typename std::remove_reference<T>::type;
|
using type = typename std::remove_reference<T>::type;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
struct lowest_layer_type_impl<T, boost::void_t<
|
struct lowest_layer_type_impl<T, true>
|
||||||
decltype(std::declval<T>().next_layer())>>
|
|
||||||
{
|
{
|
||||||
using type = typename lowest_layer_type_impl<
|
using type = typename lowest_layer_type_impl<
|
||||||
decltype(std::declval<T>().next_layer())>::type;
|
decltype(std::declval<T&>().next_layer())>::type;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
using lowest_layer_type = typename
|
using lowest_layer_type = typename
|
||||||
lowest_layer_type_impl<T>::type;
|
lowest_layer_type_impl<T>::type;
|
||||||
|
|
||||||
template<class T>
|
//---
|
||||||
lowest_layer_type<T>&
|
|
||||||
get_lowest_layer_impl(
|
|
||||||
T& t, std::true_type) noexcept
|
|
||||||
{
|
|
||||||
using type = typename std::decay<
|
|
||||||
decltype(t.next_layer())>::type;
|
|
||||||
return get_lowest_layer_impl(t.next_layer(),
|
|
||||||
has_next_layer<type>{});
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
T&
|
T&
|
||||||
@@ -66,6 +58,16 @@ get_lowest_layer_impl(
|
|||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
lowest_layer_type<T>&
|
||||||
|
get_lowest_layer_impl(
|
||||||
|
T& t, std::true_type) noexcept
|
||||||
|
{
|
||||||
|
return get_lowest_layer_impl(t.next_layer(),
|
||||||
|
has_next_layer<typename std::decay<
|
||||||
|
decltype(t.next_layer())>::type>{});
|
||||||
|
}
|
||||||
|
|
||||||
} // detail
|
} // detail
|
||||||
} // beast
|
} // beast
|
||||||
} // boost
|
} // boost
|
||||||
|
42
include/boost/beast/core/detail/static_const.hpp
Normal file
42
include/boost/beast/core/detail/static_const.hpp
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2019 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_STATIC_CONST_HPP
|
||||||
|
#define BOOST_BEAST_DETAIL_STATIC_CONST_HPP
|
||||||
|
|
||||||
|
/* This is a derivative work, original copyright:
|
||||||
|
|
||||||
|
Copyright Eric Niebler 2013-present
|
||||||
|
|
||||||
|
Use, modification and distribution is subject to 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)
|
||||||
|
|
||||||
|
Project home: https://github.com/ericniebler/range-v3
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
namespace beast {
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct static_const
|
||||||
|
{
|
||||||
|
static constexpr T value {};
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
constexpr T static_const<T>::value;
|
||||||
|
|
||||||
|
} // detail
|
||||||
|
} // beast
|
||||||
|
} // boost
|
||||||
|
|
||||||
|
#endif
|
@@ -73,6 +73,8 @@ using lowest_layer_type = detail::lowest_layer_type<T>;
|
|||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
@param t The layer in a stack of layered objects for which the lowest layer is returned.
|
@param t The layer in a stack of layered objects for which the lowest layer is returned.
|
||||||
|
|
||||||
|
@see @ref close_socket, @ref lowest_layer_type
|
||||||
*/
|
*/
|
||||||
template<class T>
|
template<class T>
|
||||||
lowest_layer_type<T>&
|
lowest_layer_type<T>&
|
||||||
|
@@ -289,9 +289,10 @@ struct is_sync_write_stream : std::false_type {};
|
|||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
struct is_sync_write_stream<T, detail::void_t<decltype(
|
struct is_sync_write_stream<T, detail::void_t<decltype(
|
||||||
|
(
|
||||||
std::declval<std::size_t&>() = std::declval<T&>().write_some(
|
std::declval<std::size_t&>() = std::declval<T&>().write_some(
|
||||||
std::declval<detail::ConstBufferSequence>()),
|
std::declval<detail::ConstBufferSequence>()))
|
||||||
std::declval<std::size_t&>() = std::declval<T&>().write_some(
|
,std::declval<std::size_t&>() = std::declval<T&>().write_some(
|
||||||
std::declval<detail::ConstBufferSequence>(),
|
std::declval<detail::ConstBufferSequence>(),
|
||||||
std::declval<boost::system::error_code&>())
|
std::declval<boost::system::error_code&>())
|
||||||
)>> : std::true_type {};
|
)>> : std::true_type {};
|
||||||
|
44
test/beast/core/_detail_static_const.cpp
Normal file
44
test/beast/core/_detail_static_const.cpp
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
//
|
||||||
|
// 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
|
||||||
|
//
|
||||||
|
|
||||||
|
// Test that header file is self-contained.
|
||||||
|
#include <boost/beast/core/detail/static_const.hpp>
|
||||||
|
|
||||||
|
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
||||||
|
|
||||||
|
#include <boost/beast/core/close_socket.hpp>
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
namespace beast {
|
||||||
|
|
||||||
|
struct foo_impl
|
||||||
|
{
|
||||||
|
void operator()() const noexcept
|
||||||
|
{
|
||||||
|
BEAST_PASS();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr auto& bar =
|
||||||
|
boost::beast::detail::static_const<detail::close_socket_impl>::value;
|
||||||
|
|
||||||
|
class static_const_test : public beast::unit_test::suite
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void
|
||||||
|
run() override
|
||||||
|
{
|
||||||
|
pass();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
BEAST_DEFINE_TESTSUITE(beast,core,static_const);
|
||||||
|
|
||||||
|
} // beast
|
||||||
|
} // boost
|
@@ -11,9 +11,12 @@
|
|||||||
#include <boost/beast/core/close_socket.hpp>
|
#include <boost/beast/core/close_socket.hpp>
|
||||||
|
|
||||||
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
||||||
|
#include <boost/beast/_experimental/test/stream.hpp>
|
||||||
#include <boost/beast/core/get_lowest_layer.hpp>
|
#include <boost/beast/core/get_lowest_layer.hpp>
|
||||||
|
#include <boost/beast/core/string.hpp>
|
||||||
|
|
||||||
#include <boost/asio/ip/tcp.hpp>
|
#include <boost/asio/ip/tcp.hpp>
|
||||||
|
#include <boost/asio/write.hpp>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
namespace boost {
|
namespace boost {
|
||||||
@@ -52,18 +55,72 @@ public:
|
|||||||
BEAST_EXPECT(! sock.is_open());
|
BEAST_EXPECT(! sock.is_open());
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
layer<net::ip::tcp::socket> layer(ioc);
|
using type = layer<net::ip::tcp::socket>;
|
||||||
|
type layer(ioc);
|
||||||
layer.next_layer().open(net::ip::tcp::v4());
|
layer.next_layer().open(net::ip::tcp::v4());
|
||||||
BEAST_EXPECT(layer.next_layer().is_open());
|
BEAST_EXPECT(layer.next_layer().is_open());
|
||||||
|
BOOST_STATIC_ASSERT(detail::has_next_layer<type>::value);
|
||||||
|
BOOST_STATIC_ASSERT((std::is_same<
|
||||||
|
typename std::decay<decltype(get_lowest_layer(layer))>::type,
|
||||||
|
lowest_layer_type<decltype(layer)>>::value));
|
||||||
|
BOOST_STATIC_ASSERT(std::is_same<net::ip::tcp::socket&,
|
||||||
|
decltype(get_lowest_layer(layer))>::value);
|
||||||
|
BOOST_STATIC_ASSERT(std::is_same<net::ip::tcp::socket,
|
||||||
|
lowest_layer_type<decltype(layer)>>::value);
|
||||||
close_socket(get_lowest_layer(layer));
|
close_socket(get_lowest_layer(layer));
|
||||||
BEAST_EXPECT(! layer.next_layer().is_open());
|
BEAST_EXPECT(! layer.next_layer().is_open());
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
test::stream ts(ioc);
|
||||||
|
close_socket(ts);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
template <class WriteStream>
|
||||||
|
void hello_and_close (WriteStream& stream)
|
||||||
|
{
|
||||||
|
net::write(stream, net::const_buffer("Hello, world!", 13));
|
||||||
|
close_socket(get_lowest_layer(stream));
|
||||||
|
}
|
||||||
|
|
||||||
|
class my_socket
|
||||||
|
{
|
||||||
|
net::ip::tcp::socket sock_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
my_socket(net::io_context& ioc)
|
||||||
|
: sock_(ioc)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
friend void beast_close_socket(my_socket& s)
|
||||||
|
{
|
||||||
|
error_code ec;
|
||||||
|
s.sock_.close(ec);
|
||||||
|
// ignore the error
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
testJavadocs()
|
||||||
|
{
|
||||||
|
BEAST_EXPECT(&close_socket_test::template hello_and_close<net::ip::tcp::socket>);
|
||||||
|
{
|
||||||
|
net::io_context ioc;
|
||||||
|
my_socket s(ioc);
|
||||||
|
close_socket(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
void
|
void
|
||||||
run() override
|
run() override
|
||||||
{
|
{
|
||||||
testClose();
|
testClose();
|
||||||
|
testJavadocs();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -34,7 +34,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
std::size_t write_some(T const&, error_code&)
|
std::size_t write_some(T const&, boost::system::error_code&)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -163,8 +163,9 @@ public:
|
|||||||
void
|
void
|
||||||
testJavadoc()
|
testJavadoc()
|
||||||
{
|
{
|
||||||
using type = write_stream<without>;
|
write_stream<without> s;
|
||||||
type s;
|
BOOST_STATIC_ASSERT(
|
||||||
|
is_sync_write_stream<without>::value);
|
||||||
BOOST_STATIC_ASSERT(std::is_same<
|
BOOST_STATIC_ASSERT(std::is_same<
|
||||||
decltype(get_lowest_layer(s)), without&>::value);
|
decltype(get_lowest_layer(s)), without&>::value);
|
||||||
|
|
||||||
|
@@ -35,15 +35,6 @@ public:
|
|||||||
is_mutable_dynamic_buffer<
|
is_mutable_dynamic_buffer<
|
||||||
static_buffer_base>::value);
|
static_buffer_base>::value);
|
||||||
|
|
||||||
#if ! defined( BOOST_LIBSTDCXX_VERSION ) || BOOST_LIBSTDCXX_VERSION >= 50000
|
|
||||||
# ifndef BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
|
|
||||||
BOOST_STATIC_ASSERT(std::is_trivially_copyable<
|
|
||||||
static_buffer_base::const_buffers_type>::value);
|
|
||||||
BOOST_STATIC_ASSERT(std::is_trivially_copyable<
|
|
||||||
static_buffer_base::mutable_data_type>::value);
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void
|
void
|
||||||
testDynamicBuffer()
|
testDynamicBuffer()
|
||||||
{
|
{
|
||||||
|
@@ -10,6 +10,7 @@
|
|||||||
// Test that header file is self-contained.
|
// Test that header file is self-contained.
|
||||||
#include <boost/beast/core/type_traits.hpp>
|
#include <boost/beast/core/type_traits.hpp>
|
||||||
|
|
||||||
|
#include <boost/beast/_experimental/test/stream.hpp>
|
||||||
#include <boost/asio/ip/tcp.hpp>
|
#include <boost/asio/ip/tcp.hpp>
|
||||||
#include <boost/asio/streambuf.hpp>
|
#include <boost/asio/streambuf.hpp>
|
||||||
#include <boost/asio/detail/consuming_buffers.hpp>
|
#include <boost/asio/detail/consuming_buffers.hpp>
|
||||||
@@ -82,6 +83,46 @@ BOOST_STATIC_ASSERT(! is_completion_handler<H, void(void)>::value);
|
|||||||
// stream concepts
|
// stream concepts
|
||||||
//
|
//
|
||||||
|
|
||||||
|
struct sync_write_stream
|
||||||
|
{
|
||||||
|
net::io_context&
|
||||||
|
get_io_service();
|
||||||
|
|
||||||
|
template<class ConstBufferSequence>
|
||||||
|
std::size_t
|
||||||
|
write_some(ConstBufferSequence const& buffers);
|
||||||
|
|
||||||
|
template<class ConstBufferSequence>
|
||||||
|
std::size_t
|
||||||
|
write_some(
|
||||||
|
ConstBufferSequence const& buffers, error_code& ec);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sync_read_stream
|
||||||
|
{
|
||||||
|
template<class MutableBufferSequence>
|
||||||
|
std::size_t
|
||||||
|
read_some(MutableBufferSequence const& buffers);
|
||||||
|
|
||||||
|
template<class MutableBufferSequence>
|
||||||
|
std::size_t
|
||||||
|
read_some(MutableBufferSequence const& buffers,
|
||||||
|
error_code& ec);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sync_stream : sync_read_stream, sync_write_stream
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT(! is_sync_read_stream<sync_write_stream>::value);
|
||||||
|
BOOST_STATIC_ASSERT(! is_sync_write_stream<sync_read_stream>::value);
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT(is_sync_read_stream<sync_read_stream>::value);
|
||||||
|
BOOST_STATIC_ASSERT(is_sync_write_stream<sync_write_stream>::value);
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT(is_sync_read_stream<sync_stream>::value);
|
||||||
|
BOOST_STATIC_ASSERT(is_sync_write_stream<sync_stream>::value);
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
using stream_type = net::ip::tcp::socket;
|
using stream_type = net::ip::tcp::socket;
|
||||||
@@ -106,6 +147,11 @@ BOOST_STATIC_ASSERT(! is_async_write_stream<not_a_stream>::value);
|
|||||||
BOOST_STATIC_ASSERT(! is_sync_read_stream<not_a_stream>::value);
|
BOOST_STATIC_ASSERT(! is_sync_read_stream<not_a_stream>::value);
|
||||||
BOOST_STATIC_ASSERT(! is_sync_write_stream<not_a_stream>::value);
|
BOOST_STATIC_ASSERT(! is_sync_write_stream<not_a_stream>::value);
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT(is_sync_read_stream<test::stream>::value);
|
||||||
|
BOOST_STATIC_ASSERT(is_sync_write_stream<test::stream>::value);
|
||||||
|
BOOST_STATIC_ASSERT(is_async_read_stream<test::stream>::value);
|
||||||
|
BOOST_STATIC_ASSERT(is_async_write_stream<test::stream>::value);
|
||||||
|
|
||||||
} // (anonymous)
|
} // (anonymous)
|
||||||
|
|
||||||
} // beast
|
} // beast
|
||||||
|
Reference in New Issue
Block a user