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:
Vinnie Falco
2019-02-01 14:05:07 -08:00
parent 6a658b5c3a
commit 49deee4a69
15 changed files with 361 additions and 62 deletions
+44
View 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
+58 -1
View File
@@ -11,9 +11,12 @@
#include <boost/beast/core/close_socket.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/string.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/write.hpp>
#include <utility>
namespace boost {
@@ -52,18 +55,72 @@ public:
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());
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));
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
run() override
{
testClose();
testJavadocs();
}
};
+4 -3
View File
@@ -34,7 +34,7 @@ public:
}
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;
}
@@ -163,8 +163,9 @@ public:
void
testJavadoc()
{
using type = write_stream<without>;
type s;
write_stream<without> s;
BOOST_STATIC_ASSERT(
is_sync_write_stream<without>::value);
BOOST_STATIC_ASSERT(std::is_same<
decltype(get_lowest_layer(s)), without&>::value);
-9
View File
@@ -35,15 +35,6 @@ public:
is_mutable_dynamic_buffer<
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
testDynamicBuffer()
{
+46
View File
@@ -10,6 +10,7 @@
// Test that header file is self-contained.
#include <boost/beast/core/type_traits.hpp>
#include <boost/beast/_experimental/test/stream.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/streambuf.hpp>
#include <boost/asio/detail/consuming_buffers.hpp>
@@ -82,6 +83,46 @@ BOOST_STATIC_ASSERT(! is_completion_handler<H, void(void)>::value);
// 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 {
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_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)
} // beast