mirror of
https://github.com/boostorg/beast.git
synced 2025-07-30 21:07:26 +02:00
close_socket is in stream_traits.hpp
This commit is contained in:
@ -1,3 +1,9 @@
|
|||||||
|
Version 211:
|
||||||
|
|
||||||
|
* close_socket is in stream_traits.hpp
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
Version 210:
|
Version 210:
|
||||||
|
|
||||||
* Tidy up read implementation
|
* Tidy up read implementation
|
||||||
|
@ -23,7 +23,6 @@
|
|||||||
#include <boost/beast/core/buffers_range.hpp>
|
#include <boost/beast/core/buffers_range.hpp>
|
||||||
#include <boost/beast/core/buffers_suffix.hpp>
|
#include <boost/beast/core/buffers_suffix.hpp>
|
||||||
#include <boost/beast/core/buffers_to_string.hpp>
|
#include <boost/beast/core/buffers_to_string.hpp>
|
||||||
#include <boost/beast/core/close_socket.hpp>
|
|
||||||
#include <boost/beast/core/dynamic_buffer_ref.hpp>
|
#include <boost/beast/core/dynamic_buffer_ref.hpp>
|
||||||
#include <boost/beast/core/error.hpp>
|
#include <boost/beast/core/error.hpp>
|
||||||
#include <boost/beast/core/file.hpp>
|
#include <boost/beast/core/file.hpp>
|
||||||
|
@ -1,133 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2018 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_CLOSE_SOCKET_HPP
|
|
||||||
#define BOOST_BEAST_CLOSE_SOCKET_HPP
|
|
||||||
|
|
||||||
#include <boost/beast/core/detail/config.hpp>
|
|
||||||
#include <boost/beast/core/detail/static_const.hpp>
|
|
||||||
#include <boost/asio/basic_socket.hpp>
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
namespace beast {
|
|
||||||
|
|
||||||
/** Default socket close function.
|
|
||||||
|
|
||||||
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
|
|
||||||
beast_close_socket(
|
|
||||||
net::basic_socket<Protocol BOOST_ASIO_SVC_TPARAM>& sock)
|
|
||||||
{
|
|
||||||
boost::system::error_code 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
|
|
||||||
|
|
||||||
/** Close a socket or socket-like object.
|
|
||||||
|
|
||||||
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>
|
|
||||||
void
|
|
||||||
close_socket(Socket& sock);
|
|
||||||
#else
|
|
||||||
BOOST_BEAST_INLINE_VARIABLE(close_socket, detail::close_socket_impl)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} // beast
|
|
||||||
} // boost
|
|
||||||
|
|
||||||
#endif
|
|
@ -11,7 +11,9 @@
|
|||||||
#define BOOST_BEAST_STREAM_TRAITS_HPP
|
#define BOOST_BEAST_STREAM_TRAITS_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/beast/core/detail/stream_traits.hpp>
|
#include <boost/beast/core/detail/stream_traits.hpp>
|
||||||
|
#include <boost/asio/basic_socket.hpp>
|
||||||
|
|
||||||
namespace boost {
|
namespace boost {
|
||||||
namespace beast {
|
namespace beast {
|
||||||
@ -424,6 +426,118 @@ using is_async_stream = std::integral_constant<bool,
|
|||||||
is_async_read_stream<T>::value && is_async_write_stream<T>::value>;
|
is_async_read_stream<T>::value && is_async_write_stream<T>::value>;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/** Default socket close function.
|
||||||
|
|
||||||
|
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
|
||||||
|
beast_close_socket(
|
||||||
|
net::basic_socket<Protocol BOOST_ASIO_SVC_TPARAM>& sock)
|
||||||
|
{
|
||||||
|
boost::system::error_code 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
|
||||||
|
|
||||||
|
/** Close a socket or socket-like object.
|
||||||
|
|
||||||
|
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>
|
||||||
|
void
|
||||||
|
close_socket(Socket& sock);
|
||||||
|
#else
|
||||||
|
BOOST_BEAST_INLINE_VARIABLE(close_socket, detail::close_socket_impl)
|
||||||
|
#endif
|
||||||
|
|
||||||
} // beast
|
} // beast
|
||||||
} // boost
|
} // boost
|
||||||
|
|
||||||
|
@ -42,7 +42,6 @@ add_executable (tests-beast-core
|
|||||||
buffers_range.cpp
|
buffers_range.cpp
|
||||||
buffers_suffix.cpp
|
buffers_suffix.cpp
|
||||||
buffers_to_string.cpp
|
buffers_to_string.cpp
|
||||||
close_socket.cpp
|
|
||||||
dynamic_buffer_ref.cpp
|
dynamic_buffer_ref.cpp
|
||||||
error.cpp
|
error.cpp
|
||||||
file.cpp
|
file.cpp
|
||||||
|
@ -30,7 +30,6 @@ local SOURCES =
|
|||||||
buffers_range.cpp
|
buffers_range.cpp
|
||||||
buffers_suffix.cpp
|
buffers_suffix.cpp
|
||||||
buffers_to_string.cpp
|
buffers_to_string.cpp
|
||||||
close_socket.cpp
|
|
||||||
dynamic_buffer_ref.cpp
|
dynamic_buffer_ref.cpp
|
||||||
error.cpp
|
error.cpp
|
||||||
file.cpp
|
file.cpp
|
||||||
|
@ -25,97 +25,6 @@ namespace beast {
|
|||||||
class close_socket_test : public beast::unit_test::suite
|
class close_socket_test : public beast::unit_test::suite
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
template<class T>
|
|
||||||
struct layer
|
|
||||||
{
|
|
||||||
T t;
|
|
||||||
|
|
||||||
template<class U>
|
|
||||||
explicit
|
|
||||||
layer(U&& u)
|
|
||||||
: t(std::forward<U>(u))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
T& next_layer()
|
|
||||||
{
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
|
||||||
testClose()
|
|
||||||
{
|
|
||||||
net::io_context ioc;
|
|
||||||
{
|
|
||||||
net::ip::tcp::socket sock(ioc);
|
|
||||||
sock.open(net::ip::tcp::v4());
|
|
||||||
BEAST_EXPECT(sock.is_open());
|
|
||||||
close_socket(get_lowest_layer(sock));
|
|
||||||
BEAST_EXPECT(! sock.is_open());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
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
|
void
|
||||||
run() override
|
run() override
|
||||||
{
|
{
|
||||||
|
@ -12,7 +12,12 @@
|
|||||||
|
|
||||||
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
||||||
#include <boost/beast/core/error.hpp>
|
#include <boost/beast/core/error.hpp>
|
||||||
|
#include <boost/beast/_experimental/test/stream.hpp>
|
||||||
|
#include <boost/beast/core/string.hpp>
|
||||||
#include <boost/asio/io_context.hpp>
|
#include <boost/asio/io_context.hpp>
|
||||||
|
#include <boost/asio/ip/tcp.hpp>
|
||||||
|
#include <boost/asio/write.hpp>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
namespace boost {
|
namespace boost {
|
||||||
namespace beast {
|
namespace beast {
|
||||||
@ -267,6 +272,97 @@ public:
|
|||||||
|
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
struct layer
|
||||||
|
{
|
||||||
|
T t;
|
||||||
|
|
||||||
|
template<class U>
|
||||||
|
explicit
|
||||||
|
layer(U&& u)
|
||||||
|
: t(std::forward<U>(u))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
T& next_layer()
|
||||||
|
{
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
testClose()
|
||||||
|
{
|
||||||
|
net::io_context ioc;
|
||||||
|
{
|
||||||
|
net::ip::tcp::socket sock(ioc);
|
||||||
|
sock.open(net::ip::tcp::v4());
|
||||||
|
BEAST_EXPECT(sock.is_open());
|
||||||
|
close_socket(get_lowest_layer(sock));
|
||||||
|
BEAST_EXPECT(! sock.is_open());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
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
|
||||||
|
testCloseJavadoc()
|
||||||
|
{
|
||||||
|
BEAST_EXPECT(&stream_traits_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
|
||||||
{
|
{
|
||||||
@ -274,6 +370,8 @@ public:
|
|||||||
testGetLowestLayerJavadoc();
|
testGetLowestLayerJavadoc();
|
||||||
testExecutorType();
|
testExecutorType();
|
||||||
testExecutorTypeJavadoc();
|
testExecutorTypeJavadoc();
|
||||||
|
testClose();
|
||||||
|
testCloseJavadoc();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user