mirror of
https://github.com/boostorg/beast.git
synced 2025-07-29 20:37:31 +02:00
stranded_socket tests and tidy
This commit is contained in:
@ -2,6 +2,7 @@ Version 212:
|
||||
|
||||
* dynamic_buffer_ref tests and tidy
|
||||
* flat_stream tests and tidy
|
||||
* stranded_socket tests and tidy
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
@ -113,30 +113,4 @@ synchronous stream may check its argument:
|
||||
|
||||
[snippet_core_3]
|
||||
|
||||
|
||||
|
||||
[heading Stream Interfaces]
|
||||
|
||||
To facilitiate stream algorithms, these types provide enhanced functionality
|
||||
above what is offered by networking:
|
||||
|
||||
[table Stream Interfaces
|
||||
[[Name][Description]]
|
||||
[[
|
||||
[link beast.ref.boost__beast__basic_timeout_stream `basic_timeout_stream`]
|
||||
[link beast.ref.boost__beast__timeout_stream `timeout_stream`]
|
||||
][
|
||||
Objects of this type are designed to act as a replacement for the
|
||||
traditional networking socket. They
|
||||
]]
|
||||
[[
|
||||
[link beast.ref.boost__beast__flat_stream `flat_stream`]
|
||||
][
|
||||
This stream wrapper improves performance by working around a limitation
|
||||
of networking's `ssl::stream` to improve performance.
|
||||
]]
|
||||
]
|
||||
|
||||
|
||||
|
||||
[endsect]
|
||||
|
@ -110,7 +110,7 @@ facilities for authoring and working with layered streams:
|
||||
a work-around for a performance limitation in the original SSL stream.
|
||||
]]
|
||||
[[
|
||||
[link beast.ref.boost__beast__stranded_stream `stranded_stream`]
|
||||
[link beast.ref.boost__beast__stranded_socket `stranded_socket`]
|
||||
][
|
||||
A timeout stream meets the requirements for synchronous and asynchronous
|
||||
read and write streams by passing I/O through to an underlying
|
||||
@ -131,4 +131,3 @@ streams:
|
||||
[code_core_3_layers_5]
|
||||
|
||||
[endsect]
|
||||
|
||||
|
@ -46,7 +46,7 @@
|
||||
<member><link linkend="beast.ref.boost__beast__span">span</link></member>
|
||||
<member><link linkend="beast.ref.boost__beast__static_string">static_string</link></member>
|
||||
<member><link linkend="beast.ref.boost__beast__stable_async_op_base">stable_async_op_base</link> <emphasis role="green">🞲</emphasis></member>
|
||||
<member><link linkend="beast.ref.boost__beast__stranded_stream">stranded_stream</link> <emphasis role="green">🞲</emphasis></member>
|
||||
<member><link linkend="beast.ref.boost__beast__stranded_socket">stranded_socket</link> <emphasis role="green">🞲</emphasis></member>
|
||||
<member><link linkend="beast.ref.boost__beast__string_param">string_param</link></member>
|
||||
<member><link linkend="beast.ref.boost__beast__string_view">string_view</link></member>
|
||||
<member><link linkend="beast.ref.boost__beast__timeout_stream">timeout_stream</link> <emphasis role="green">🞲</emphasis></member>
|
||||
@ -69,6 +69,7 @@
|
||||
<member><link linkend="beast.ref.boost__beast__bind_handler">bind_handler</link></member>
|
||||
<member><link linkend="beast.ref.boost__beast__buffer_size">buffer_size</link> <emphasis role="green">🞲</emphasis></member>
|
||||
<member><link linkend="beast.ref.boost__beast__close_socket">close_socket</link> <emphasis role="green">🞲</emphasis></member>
|
||||
<member><link linkend="beast.ref.boost__beast__connect">connect</link> <emphasis role="green">🞲</emphasis></member>
|
||||
<member><link linkend="beast.ref.boost__beast__generic_category">generic_category</link></member>
|
||||
<member><link linkend="beast.ref.boost__beast__get_lowest_layer">get_lowest_layer</link> <emphasis role="green">🞲</emphasis></member>
|
||||
<member><link linkend="beast.ref.boost__beast__iequals">iequals</link></member>
|
||||
|
@ -39,6 +39,9 @@
|
||||
<xsl:when test="type = 'class EndpointSequence'">
|
||||
<xsl:text>class __EndpointSequence__</xsl:text>
|
||||
</xsl:when>
|
||||
<xsl:when test="type = 'class ExecutionContext'">
|
||||
<xsl:text>class __ExecutionContext__</xsl:text>
|
||||
</xsl:when>
|
||||
<xsl:when test="type = 'class Executor'">
|
||||
<xsl:text>class __Executor__</xsl:text>
|
||||
</xsl:when>
|
||||
|
@ -41,7 +41,7 @@
|
||||
#include <boost/beast/core/span.hpp>
|
||||
#include <boost/beast/core/static_buffer.hpp>
|
||||
#include <boost/beast/core/static_string.hpp>
|
||||
#include <boost/beast/core/stranded_stream.hpp>
|
||||
#include <boost/beast/core/stranded_socket.hpp>
|
||||
#include <boost/beast/core/stream_traits.hpp>
|
||||
#include <boost/beast/core/string.hpp>
|
||||
#include <boost/beast/core/string_param.hpp>
|
||||
|
@ -682,6 +682,7 @@ async_connect(
|
||||
indicate success. The @c next parameter is the next endpoint to be tried.
|
||||
The function object should return true if the next endpoint should be tried,
|
||||
and false if it should be skipped.
|
||||
|
||||
@param handler The handler to be called when the connect operation
|
||||
completes. Ownership of the handler may be transferred. The function
|
||||
signature of the handler must be:
|
||||
@ -701,7 +702,7 @@ async_connect(
|
||||
not, the handler will not be invoked from within this function. Invocation
|
||||
of the handler will be performed in a manner equivalent to using
|
||||
`net::io_context::post()`.
|
||||
|
||||
|
||||
@par Example
|
||||
The following connect condition function object can be used to output
|
||||
information about the individual connection attempts:
|
||||
|
@ -7,8 +7,8 @@
|
||||
// Official repository: https://github.com/boostorg/beast
|
||||
//
|
||||
|
||||
#ifndef BOOST_BEAST_CORE_DETAIL_STRANDED_STREAM_HPP
|
||||
#define BOOST_BEAST_CORE_DETAIL_STRANDED_STREAM_HPP
|
||||
#ifndef BOOST_BEAST_CORE_DETAIL_STRANDED_SOCKET_HPP
|
||||
#define BOOST_BEAST_CORE_DETAIL_STRANDED_SOCKET_HPP
|
||||
|
||||
#include <boost/beast/core/detail/bind_default_executor.hpp>
|
||||
#include <boost/asio/basic_stream_socket.hpp>
|
||||
@ -19,20 +19,20 @@ namespace beast {
|
||||
namespace detail {
|
||||
|
||||
template<class Protocol>
|
||||
class stranded_stream_base
|
||||
class stranded_socket_base
|
||||
{
|
||||
protected:
|
||||
net::basic_stream_socket<Protocol> socket_;
|
||||
|
||||
template<class... Args>
|
||||
explicit
|
||||
stranded_stream_base(Args&&... args)
|
||||
stranded_socket_base(Args&&... args)
|
||||
: socket_(std::forward<Args>(args)...)
|
||||
{
|
||||
}
|
||||
|
||||
stranded_stream_base(stranded_stream_base&&) = default;
|
||||
stranded_stream_base& operator=(stranded_stream_base&&) = default;
|
||||
stranded_socket_base(stranded_socket_base&&) = default;
|
||||
stranded_socket_base& operator=(stranded_socket_base&&) = delete;
|
||||
};
|
||||
|
||||
} // detail
|
1102
include/boost/beast/core/stranded_socket.hpp
Normal file
1102
include/boost/beast/core/stranded_socket.hpp
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,433 +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_CORE_STRANDED_STREAM_HPP
|
||||
#define BOOST_BEAST_CORE_STRANDED_STREAM_HPP
|
||||
|
||||
#include <boost/beast/core/detail/config.hpp>
|
||||
#include <boost/beast/core/stream_traits.hpp>
|
||||
#include <boost/beast/core/detail/stranded_stream.hpp>
|
||||
#include <boost/beast/core/detail/type_traits.hpp>
|
||||
#include <boost/asio/async_result.hpp>
|
||||
#include <boost/asio/basic_stream_socket.hpp>
|
||||
#include <boost/asio/connect.hpp>
|
||||
#include <boost/asio/executor.hpp>
|
||||
#include <boost/core/empty_value.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** A stream socket using a custom executor, defaulting to a strand
|
||||
|
||||
This class template is parameterized on the executor type to be
|
||||
used for all asynchronous operations. This achieves partial support for
|
||||
[P1322]. The default template parameter uses a strand for the next
|
||||
layer's executor.
|
||||
|
||||
@see <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1322r0.html">[P1322R0]</a>
|
||||
<em>Networking TS enhancement to enable custom I/O executors</em>
|
||||
*/
|
||||
template<
|
||||
class Protocol,
|
||||
class Executor = beast::executor_type<net::basic_stream_socket<Protocol>>
|
||||
>
|
||||
class stranded_stream
|
||||
#ifndef BOOST_BEAST_DOXYGEN
|
||||
: private detail::stranded_stream_base<Protocol>
|
||||
, private boost::empty_value<Executor>
|
||||
#endif
|
||||
{
|
||||
// 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()");
|
||||
|
||||
public:
|
||||
/// The type of the executor associated with the object.
|
||||
using executor_type = Executor;
|
||||
|
||||
/// The type of the next layer.
|
||||
using next_layer_type = net::basic_stream_socket<Protocol>;
|
||||
|
||||
/// The protocol type.
|
||||
using protocol_type = Protocol;
|
||||
|
||||
/// The endpoint type.
|
||||
using endpoint_type = typename Protocol::endpoint;
|
||||
|
||||
/** Construct the stream without opening it.
|
||||
|
||||
This constructor creates a stream. The underlying socket needs
|
||||
to be opened and then 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 for any asynchronous operations performed on the socket.
|
||||
Currently, the only supported type for `ctx` is `net::io_context`.
|
||||
|
||||
@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 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1322r0.html
|
||||
*/
|
||||
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
|
||||
stranded_stream(ExecutionContext& ctx, Args&&... args)
|
||||
: detail::stranded_stream_base<Protocol>(
|
||||
ctx, std::forward<Args>(args)...)
|
||||
, boost::empty_value<Executor>(
|
||||
boost::empty_init_t{}, ctx.get_executor())
|
||||
{
|
||||
// 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");
|
||||
}
|
||||
|
||||
/** Construct the stream without opening it.
|
||||
|
||||
This constructor creates a stream. The underlying socket needs
|
||||
to be opened and then connected or accepted before data can be
|
||||
sent or received on it.
|
||||
|
||||
@param ex The executor which stream will use to dispatch handlers for
|
||||
any asynchronous operations performed on the underlying socket.
|
||||
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 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1322r0.html
|
||||
*/
|
||||
template<class... Args>
|
||||
explicit
|
||||
stranded_stream(executor_type const& ex, Args&&... args)
|
||||
: detail::stranded_stream_base<Protocol>(
|
||||
ex.context(), std::forward<Args>(args)...)
|
||||
, boost::empty_value<Executor>(
|
||||
boost::empty_init_t{}, ex)
|
||||
{
|
||||
// Restriction is necessary until Asio fully supports P1322R0
|
||||
if(ex.context().get_executor() != this->socket_.get_executor())
|
||||
throw std::invalid_argument(
|
||||
"ctx.get_executor() != socket.get_executor()");
|
||||
}
|
||||
|
||||
/** Move-construct a stream from another stream
|
||||
|
||||
This constructor moves a stream from one object to another.
|
||||
|
||||
The behavior of moving a stream while asynchronous operations
|
||||
are outstanding is undefined.
|
||||
|
||||
@param other The other object from which the move will occur.
|
||||
|
||||
@note Following the move, the moved-from object is in a newly
|
||||
constructed state.
|
||||
*/
|
||||
stranded_stream(stranded_stream&& other) = default;
|
||||
|
||||
/** Move-assign a stream from another stream
|
||||
|
||||
This assignment operator moves a stream socket from one object
|
||||
to another.
|
||||
|
||||
The behavior of move assignment while asynchronous operations
|
||||
are pending is undefined.
|
||||
|
||||
@param other The other basic_timeout_stream object from which the
|
||||
move will occur.
|
||||
|
||||
@note Following the move, the moved-from object is a newly
|
||||
constructed state.
|
||||
*/
|
||||
stranded_stream&
|
||||
operator=(stranded_stream&& other) = default;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/** Return the executor associated with the object.
|
||||
|
||||
@return A copy of the executor that stream will use to dispatch handlers.
|
||||
*/
|
||||
executor_type
|
||||
get_executor() const noexcept
|
||||
{
|
||||
return this->get();
|
||||
}
|
||||
|
||||
/** Get a reference to the underlying socket.
|
||||
|
||||
This function returns a reference to the next layer
|
||||
in a stack of stream layers.
|
||||
|
||||
@return A reference to the next layer in the stack of
|
||||
stream layers.
|
||||
*/
|
||||
next_layer_type&
|
||||
next_layer() noexcept
|
||||
{
|
||||
return this->socket_;
|
||||
}
|
||||
|
||||
/** Get a reference to the underlying socket.
|
||||
|
||||
This function returns a reference to the next layer in a
|
||||
stack of stream layers.
|
||||
|
||||
@return A reference to the next layer in the stack of
|
||||
stream layers.
|
||||
*/
|
||||
next_layer_type const&
|
||||
next_layer() const noexcept
|
||||
{
|
||||
return this->socket_;
|
||||
}
|
||||
|
||||
/** Start an asynchronous connect.
|
||||
|
||||
This function is used to asynchronously connect a socket to the
|
||||
specified remote endpoint. The function call always returns immediately.
|
||||
|
||||
The underlying socket is automatically opened if it is not already open.
|
||||
If the connect fails, and the socket was automatically opened, the socket
|
||||
is not returned to the closed state.
|
||||
|
||||
@param ep The remote endpoint to which the underlying socket will be
|
||||
connected. Copies will be made of the endpoint object as required.
|
||||
|
||||
@param handler The handler to be called when the operation completes.
|
||||
The implementation will take ownership of the handler by move construction.
|
||||
The handler must be invocable with this signature:
|
||||
@code
|
||||
void handler(
|
||||
error_code ec // Result of operation
|
||||
);
|
||||
@endcode
|
||||
Regardless of whether the asynchronous operation completes immediately or
|
||||
not, the handler will not be invoked from within this function. Invocation
|
||||
of the handler will be performed in a manner equivalent to using
|
||||
`net::post()`.
|
||||
*/
|
||||
template<class ConnectHandler>
|
||||
BOOST_ASIO_INITFN_RESULT_TYPE(ConnectHandler,
|
||||
void(error_code))
|
||||
async_connect(
|
||||
endpoint_type ep,
|
||||
ConnectHandler&& handler);
|
||||
|
||||
/** Read some data from the stream.
|
||||
|
||||
This function is used to read data from the stream. The function call will
|
||||
block until one or more bytes of data has been read successfully, or until
|
||||
an error occurs.
|
||||
|
||||
@param buffers The buffers into which the data will be read.
|
||||
|
||||
@returns The number of bytes read.
|
||||
|
||||
@throws boost::system::system_error Thrown on failure.
|
||||
|
||||
@note The `read_some` operation may not read all of the requested number of
|
||||
bytes. Consider using the function `net::read` if you need to ensure
|
||||
that the requested amount of data is read before the blocking operation
|
||||
completes.
|
||||
*/
|
||||
template<class MutableBufferSequence>
|
||||
std::size_t
|
||||
read_some(MutableBufferSequence const& buffers)
|
||||
{
|
||||
return this->socket_.read_some(buffers);
|
||||
}
|
||||
|
||||
/** Read some data from the stream.
|
||||
|
||||
This function is used to read data from the stream. The function call will
|
||||
block until one or more bytes of data has been read successfully, or until
|
||||
an error occurs.
|
||||
|
||||
@param buffers The buffers into which the data will be read.
|
||||
|
||||
@param ec Set to indicate what error occurred, if any.
|
||||
|
||||
@returns The number of bytes read.
|
||||
|
||||
@note The `read_some` operation may not read all of the requested number of
|
||||
bytes. Consider using the function `net::read` if you need to ensure
|
||||
that the requested amount of data is read before the blocking operation
|
||||
completes.
|
||||
*/
|
||||
template<class MutableBufferSequence>
|
||||
std::size_t
|
||||
read_some(
|
||||
MutableBufferSequence const& buffers,
|
||||
error_code& ec)
|
||||
{
|
||||
return this->socket_.read_some(buffers, ec);
|
||||
}
|
||||
|
||||
/** Start an asynchronous read.
|
||||
|
||||
This function is used to asynchronously read data from the stream.
|
||||
The function call always returns immediately.
|
||||
|
||||
@param buffers A range of zero or more buffers to read stream data into.
|
||||
Although the buffers object may be copied as necessary, ownership of the
|
||||
underlying memory blocks is retained by the caller, which must guarantee
|
||||
that they remain valid until the handler is called.
|
||||
|
||||
@param handler The handler to be called when the operation completes.
|
||||
The implementation will take ownership of the handler by move construction.
|
||||
The handler must be invocable with this signature:
|
||||
@code
|
||||
void handler(
|
||||
error_code error, // Result of operation.
|
||||
std::size_t bytes_transferred // Number of bytes read.
|
||||
);
|
||||
@endcode
|
||||
Regardless of whether the asynchronous operation completes immediately or
|
||||
not, the handler will not be invoked from within this function. Invocation
|
||||
of the handler will be performed in a manner equivalent to using
|
||||
`net::post()`.
|
||||
*/
|
||||
template<class MutableBufferSequence, class ReadHandler>
|
||||
BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
|
||||
void(error_code, std::size_t))
|
||||
async_read_some(
|
||||
MutableBufferSequence const& buffers,
|
||||
ReadHandler&& handler)
|
||||
{
|
||||
BOOST_BEAST_HANDLER_INIT(ReadHandler,
|
||||
void(error_code, std::size_t));
|
||||
this->socket_.async_read_some(
|
||||
buffers,
|
||||
detail::bind_default_executor(
|
||||
this->get(),
|
||||
std::move(init.completion_handler)));
|
||||
return init.result.get();
|
||||
}
|
||||
|
||||
/** Write some data to the stream.
|
||||
|
||||
This function is used to write data on the stream. The function call will
|
||||
block until one or more bytes of data has been written successfully, or
|
||||
until an error occurs.
|
||||
|
||||
@param buffers The data to be written.
|
||||
|
||||
@returns The number of bytes written.
|
||||
|
||||
@throws boost::system::system_error Thrown on failure.
|
||||
|
||||
@note The `write_some` operation may not transmit all of the data to the
|
||||
peer. Consider using the function `net::write` if you need to
|
||||
ensure that all data is written before the blocking operation completes.
|
||||
*/
|
||||
template<class ConstBufferSequence>
|
||||
std::size_t
|
||||
write_some(ConstBufferSequence const& buffers)
|
||||
{
|
||||
return this->socket_.write_some(buffers);
|
||||
}
|
||||
|
||||
/** Write some data to the stream.
|
||||
|
||||
This function is used to write data on the stream. The function call will
|
||||
block until one or more bytes of data has been written successfully, or
|
||||
until an error occurs.
|
||||
|
||||
@param buffers The data to be written.
|
||||
|
||||
@param ec Set to indicate what error occurred, if any.
|
||||
|
||||
@returns The number of bytes written.
|
||||
|
||||
@note The `write_some` operation may not transmit all of the data to the
|
||||
peer. Consider using the function `net::write` if you need to
|
||||
ensure that all data is written before the blocking operation completes.
|
||||
*/
|
||||
template<class ConstBufferSequence>
|
||||
std::size_t
|
||||
write_some(
|
||||
ConstBufferSequence const& buffers,
|
||||
error_code& ec)
|
||||
{
|
||||
return this->socket_.write_some(buffers, ec);
|
||||
}
|
||||
|
||||
/** Start an asynchronous write.
|
||||
|
||||
This function is used to asynchronously write data to the stream.
|
||||
The function call always returns immediately.
|
||||
|
||||
@param buffers A range of zero or more buffers to be written to the stream.
|
||||
Although the buffers object may be copied as necessary, ownership of the
|
||||
underlying memory blocks is retained by the caller, which must guarantee
|
||||
that they remain valid until the handler is called.
|
||||
|
||||
@param handler The handler to be called when the operation completes.
|
||||
The implementation will take ownership of the handler by move construction.
|
||||
The handler must be invocable with this signature:
|
||||
@code
|
||||
void handler(
|
||||
error_code error, // Result of operation.
|
||||
std::size_t bytes_transferred // Number of bytes written.
|
||||
);
|
||||
@endcode
|
||||
Regardless of whether the asynchronous operation completes immediately or
|
||||
not, the handler will not be invoked from within this function. Invocation
|
||||
of the handler will be performed in a manner equivalent to using
|
||||
`net::post()`.
|
||||
*/
|
||||
template<class ConstBufferSequence, class WriteHandler>
|
||||
BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
|
||||
void(error_code, std::size_t))
|
||||
async_write_some(
|
||||
ConstBufferSequence const& buffers,
|
||||
WriteHandler&& handler)
|
||||
{
|
||||
BOOST_BEAST_HANDLER_INIT(WriteHandler,
|
||||
void(error_code, std::size_t));
|
||||
this->socket_.async_write_some(
|
||||
buffers,
|
||||
detail::bind_default_executor(
|
||||
this->get(),
|
||||
std::move(init.completion_handler)));
|
||||
return init.result.get();
|
||||
}
|
||||
};
|
||||
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
#endif
|
@ -61,7 +61,7 @@ add_executable (tests-beast-core
|
||||
span.cpp
|
||||
static_buffer.cpp
|
||||
static_string.cpp
|
||||
stranded_stream.cpp
|
||||
stranded_socket.cpp
|
||||
stream_traits.cpp
|
||||
string.cpp
|
||||
string_param.cpp
|
||||
|
@ -49,7 +49,7 @@ local SOURCES =
|
||||
span.cpp
|
||||
static_buffer.cpp
|
||||
static_string.cpp
|
||||
stranded_stream.cpp
|
||||
stranded_socket.cpp
|
||||
stream_traits.cpp
|
||||
string.cpp
|
||||
string_param.cpp
|
||||
|
@ -134,7 +134,7 @@ public:
|
||||
{
|
||||
// shouldn't be called since the enclosing
|
||||
// networking wrapper only uses dispatch
|
||||
s_.fail("unexpected post", __FILE__, __LINE__);
|
||||
BEAST_FAIL();
|
||||
}
|
||||
|
||||
template<class F, class Alloc>
|
||||
@ -142,7 +142,7 @@ public:
|
||||
{
|
||||
// shouldn't be called since the enclosing
|
||||
// networking wrapper only uses dispatch
|
||||
s_.fail("unexpected defer", __FILE__, __LINE__);
|
||||
BEAST_FAIL();
|
||||
}
|
||||
};
|
||||
|
||||
|
519
test/beast/core/stranded_socket.cpp
Normal file
519
test/beast/core/stranded_socket.cpp
Normal file
@ -0,0 +1,519 @@
|
||||
//
|
||||
// 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
|
||||
//
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include <boost/beast/core/stranded_socket.hpp>
|
||||
|
||||
#include "stream_tests.hpp"
|
||||
|
||||
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
|
||||
namespace {
|
||||
|
||||
template<class Executor = net::io_context::executor_type>
|
||||
class test_executor
|
||||
{
|
||||
public:
|
||||
// VFALCO These need to be atomic or something
|
||||
struct info
|
||||
{
|
||||
int dispatch = 0;
|
||||
int post = 0;
|
||||
int defer = 0;
|
||||
int work = 0;
|
||||
int total = 0;
|
||||
};
|
||||
|
||||
private:
|
||||
struct state
|
||||
{
|
||||
Executor ex;
|
||||
info info_;
|
||||
|
||||
state(Executor const& ex_)
|
||||
: ex(ex_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
std::shared_ptr<state> sp_;
|
||||
|
||||
public:
|
||||
test_executor(test_executor const&) = default;
|
||||
test_executor& operator=(test_executor const&) = default;
|
||||
|
||||
explicit
|
||||
test_executor(Executor const& ex)
|
||||
: sp_(std::make_shared<state>(ex))
|
||||
{
|
||||
}
|
||||
|
||||
decltype(sp_->ex.context())
|
||||
context() const noexcept
|
||||
{
|
||||
return sp_->ex.context();
|
||||
}
|
||||
|
||||
info&
|
||||
operator*() noexcept
|
||||
{
|
||||
return sp_->info_;
|
||||
}
|
||||
|
||||
info*
|
||||
operator->() noexcept
|
||||
{
|
||||
return &sp_->info_;
|
||||
}
|
||||
|
||||
void
|
||||
on_work_started() const noexcept
|
||||
{
|
||||
++sp_->info_.work;
|
||||
}
|
||||
|
||||
void
|
||||
on_work_finished() const noexcept
|
||||
{
|
||||
}
|
||||
|
||||
template<class F, class A>
|
||||
void
|
||||
dispatch(F&& f, A const& a)
|
||||
{
|
||||
++sp_->info_.dispatch;
|
||||
++sp_->info_.total;
|
||||
sp_->ex.dispatch(
|
||||
std::forward<F>(f), a);
|
||||
}
|
||||
|
||||
template<class F, class A>
|
||||
void
|
||||
post(F&& f, A const& a)
|
||||
{
|
||||
++sp_->info_.post;
|
||||
++sp_->info_.total;
|
||||
sp_->ex.post(
|
||||
std::forward<F>(f), a);
|
||||
}
|
||||
|
||||
template<class F, class A>
|
||||
void
|
||||
defer(F&& f, A const& a)
|
||||
{
|
||||
++sp_->info_.defer;
|
||||
++sp_->info_.total;
|
||||
sp_->ex.defer(
|
||||
std::forward<F>(f), a);
|
||||
}
|
||||
};
|
||||
|
||||
struct test_handler
|
||||
{
|
||||
int& flags;
|
||||
|
||||
void
|
||||
operator()()
|
||||
{
|
||||
flags |= 1;
|
||||
}
|
||||
|
||||
template<class F>
|
||||
friend
|
||||
void
|
||||
asio_handler_invoke(F&& f, test_handler* p)
|
||||
{
|
||||
p->flags |= 2;
|
||||
std::move(f)();
|
||||
}
|
||||
};
|
||||
|
||||
struct test_acceptor
|
||||
{
|
||||
net::io_context ioc;
|
||||
net::ip::tcp::acceptor a;
|
||||
net::ip::tcp::endpoint ep;
|
||||
|
||||
test_acceptor()
|
||||
: a(ioc)
|
||||
, ep(net::ip::make_address_v4("127.0.0.1"), 0)
|
||||
{
|
||||
a.open(ep.protocol());
|
||||
a.set_option(
|
||||
net::socket_base::reuse_address(true));
|
||||
a.bind(ep);
|
||||
a.listen(1);
|
||||
ep = a.local_endpoint();
|
||||
a.async_accept(
|
||||
[](error_code, net::ip::tcp::socket)
|
||||
{
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
} // (anon)
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class stranded_socket_test
|
||||
: public beast::unit_test::suite
|
||||
{
|
||||
public:
|
||||
using tcp = net::ip::tcp;
|
||||
using strand = net::io_context::strand;
|
||||
using executor = net::io_context::executor_type;
|
||||
|
||||
void
|
||||
testStream()
|
||||
{
|
||||
net::io_context ioc;
|
||||
|
||||
// default Executor
|
||||
|
||||
{
|
||||
stranded_socket<tcp> s1{strand(ioc)};
|
||||
stranded_socket<tcp> s2{strand{ioc}};
|
||||
//stranded_socket<tcp> s3{strand{ioc}}; // ambiguous parse
|
||||
}
|
||||
|
||||
// explicit Executor
|
||||
|
||||
{
|
||||
auto ex = ioc.get_executor();
|
||||
stranded_socket<tcp, executor> s1(ioc);
|
||||
stranded_socket<tcp, executor> s2(ex);
|
||||
stranded_socket<tcp, executor> s3(ioc, tcp::v4());
|
||||
stranded_socket<tcp, executor> s4(std::move(s1));
|
||||
s2.socket() = tcp::socket(ioc);
|
||||
BEAST_EXPECT(s1.get_executor() == ex);
|
||||
BEAST_EXPECT(s2.get_executor() == ex);
|
||||
BEAST_EXPECT(s3.get_executor() == ex);
|
||||
BEAST_EXPECT(s4.get_executor() == ex);
|
||||
|
||||
BEAST_EXPECT((! static_cast<
|
||||
stranded_socket<tcp, executor> const&>(
|
||||
s2).socket().is_open()));
|
||||
}
|
||||
|
||||
{
|
||||
auto ex = strand{ioc};
|
||||
stranded_socket<tcp, strand> s1(ex);
|
||||
stranded_socket<tcp, strand> s2(ex, tcp::v4());
|
||||
stranded_socket<tcp, strand> s3(std::move(s1));
|
||||
s2.socket() = tcp::socket(ioc);
|
||||
BEAST_EXPECT(s1.get_executor() == ex);
|
||||
BEAST_EXPECT(s2.get_executor() == ex);
|
||||
BEAST_EXPECT(s3.get_executor() == ex);
|
||||
|
||||
BEAST_EXPECT((! static_cast<
|
||||
stranded_socket<tcp, strand> const&>(
|
||||
s2).socket().is_open()));
|
||||
}
|
||||
|
||||
{
|
||||
test_sync_stream<stranded_socket<tcp, executor>>();
|
||||
test_async_stream<stranded_socket<tcp, executor>>();
|
||||
test_sync_stream<stranded_socket<tcp, strand>>();
|
||||
test_async_stream<stranded_socket<tcp, strand>>();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testMembers()
|
||||
{
|
||||
net::io_context ioc;
|
||||
|
||||
// connect (member)
|
||||
|
||||
auto const cond =
|
||||
[](error_code, tcp::endpoint)
|
||||
{
|
||||
return true;
|
||||
};
|
||||
|
||||
{
|
||||
stranded_socket<tcp, executor> s(ioc);
|
||||
error_code ec;
|
||||
test_acceptor a;
|
||||
try
|
||||
{
|
||||
s.connect(a.ep);
|
||||
BEAST_PASS();
|
||||
}
|
||||
catch(std::exception const&)
|
||||
{
|
||||
BEAST_FAIL();
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
stranded_socket<tcp, executor> s(ioc);
|
||||
error_code ec;
|
||||
test_acceptor a;
|
||||
s.connect(a.ep, ec);
|
||||
BEAST_EXPECT(! ec);
|
||||
}
|
||||
|
||||
// connect
|
||||
|
||||
{
|
||||
test_acceptor a;
|
||||
std::array<tcp::endpoint, 1> epa;
|
||||
epa[0] = a.ep;
|
||||
stranded_socket<tcp, executor> s(ioc);
|
||||
error_code ec;
|
||||
connect(s, epa);
|
||||
connect(s, epa, ec);
|
||||
}
|
||||
|
||||
{
|
||||
test_acceptor a;
|
||||
std::array<tcp::endpoint, 1> epa;
|
||||
epa[0] = a.ep;
|
||||
stranded_socket<tcp, executor> s(ioc);
|
||||
error_code ec;
|
||||
connect(s, epa, cond);
|
||||
connect(s, epa, cond, ec);
|
||||
}
|
||||
|
||||
{
|
||||
test_acceptor a;
|
||||
std::array<tcp::endpoint, 1> epa;
|
||||
epa[0] = a.ep;
|
||||
stranded_socket<tcp, executor> s(ioc);
|
||||
error_code ec;
|
||||
connect(s, epa.begin(), epa.end());
|
||||
connect(s, epa.begin(), epa.end(), ec);
|
||||
}
|
||||
|
||||
{
|
||||
test_acceptor a;
|
||||
std::array<tcp::endpoint, 1> epa;
|
||||
epa[0] = a.ep;
|
||||
stranded_socket<tcp, executor> s(ioc);
|
||||
error_code ec;
|
||||
connect(s, epa.begin(), epa.end(), cond);
|
||||
connect(s, epa.begin(), epa.end(), cond, ec);
|
||||
}
|
||||
|
||||
// async_connect
|
||||
|
||||
{
|
||||
stranded_socket<tcp, executor> s(ioc);
|
||||
test_acceptor a;
|
||||
error_code ec;
|
||||
s.async_connect(a. ep,
|
||||
[](error_code ec)
|
||||
{
|
||||
BEAST_EXPECT(! ec);
|
||||
});
|
||||
ioc.run();
|
||||
ioc.restart();
|
||||
}
|
||||
|
||||
{
|
||||
std::array<tcp::endpoint, 1> epa;
|
||||
epa[0] = tcp::endpoint(
|
||||
net::ip::make_address_v4("127.0.0.1"), 0);
|
||||
stranded_socket<tcp, executor> s(ioc);
|
||||
async_connect(s, epa,
|
||||
[](error_code, tcp::endpoint)
|
||||
{
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
std::array<tcp::endpoint, 1> epa;
|
||||
epa[0] = tcp::endpoint(
|
||||
net::ip::make_address_v4("127.0.0.1"), 0);
|
||||
stranded_socket<tcp, executor> s(ioc);
|
||||
async_connect(s, epa, cond,
|
||||
[](error_code, tcp::endpoint)
|
||||
{
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
std::array<tcp::endpoint, 1> epa;
|
||||
epa[0] = tcp::endpoint(
|
||||
net::ip::make_address_v4("127.0.0.1"), 0);
|
||||
using iter_type = decltype(epa)::const_iterator;
|
||||
stranded_socket<tcp, executor> s(ioc);
|
||||
async_connect(s, epa.begin(), epa.end(),
|
||||
[](error_code, iter_type)
|
||||
{
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
std::array<tcp::endpoint, 1> epa;
|
||||
epa[0] = tcp::endpoint(
|
||||
net::ip::make_address_v4("127.0.0.1"), 0);
|
||||
using iter_type = decltype(epa)::const_iterator;
|
||||
stranded_socket<tcp, executor> s(ioc);
|
||||
async_connect(s, epa.begin(), epa.end(), cond,
|
||||
[](error_code, iter_type)
|
||||
{
|
||||
});
|
||||
}
|
||||
|
||||
// read/write
|
||||
|
||||
{
|
||||
error_code ec;
|
||||
stranded_socket<tcp, executor> s(ioc, tcp::v4());
|
||||
|
||||
BEAST_EXPECT(s.read_some(net::mutable_buffer{}) == 0);
|
||||
BEAST_EXPECT(s.read_some(net::mutable_buffer{}, ec) == 0);
|
||||
BEAST_EXPECTS(! ec, ec.message());
|
||||
|
||||
BEAST_EXPECT(s.write_some(net::const_buffer{}) == 0);
|
||||
BEAST_EXPECT(s.write_some(net::const_buffer{}, ec) == 0);
|
||||
BEAST_EXPECTS(! ec, ec.message());
|
||||
|
||||
bool invoked;
|
||||
|
||||
invoked = false;
|
||||
s.async_read_some(net::mutable_buffer{},
|
||||
[&](error_code ec, std::size_t)
|
||||
{
|
||||
invoked = true;
|
||||
BEAST_EXPECTS(! ec, ec.message());
|
||||
});
|
||||
ioc.run();
|
||||
ioc.restart();
|
||||
BEAST_EXPECT(invoked);
|
||||
|
||||
invoked = false;
|
||||
s.async_write_some(net::const_buffer{},
|
||||
[&](error_code ec, std::size_t)
|
||||
{
|
||||
invoked = true;
|
||||
BEAST_EXPECTS(! ec, ec.message());
|
||||
});
|
||||
ioc.run();
|
||||
ioc.restart();
|
||||
BEAST_EXPECT(invoked);
|
||||
}
|
||||
|
||||
// stranded
|
||||
|
||||
{
|
||||
error_code ec;
|
||||
stranded_socket<tcp, strand> s(strand(ioc), tcp::v4());
|
||||
|
||||
bool invoked;
|
||||
|
||||
invoked = false;
|
||||
s.async_read_some(net::mutable_buffer{},
|
||||
[&](error_code ec, std::size_t)
|
||||
{
|
||||
invoked = true;
|
||||
BEAST_EXPECTS(! ec, ec.message());
|
||||
});
|
||||
ioc.run();
|
||||
ioc.restart();
|
||||
BEAST_EXPECT(invoked);
|
||||
|
||||
invoked = false;
|
||||
s.async_write_some(net::const_buffer{},
|
||||
[&](error_code ec, std::size_t)
|
||||
{
|
||||
invoked = true;
|
||||
BEAST_EXPECTS(! ec, ec.message());
|
||||
});
|
||||
ioc.run();
|
||||
ioc.restart();
|
||||
BEAST_EXPECT(invoked);
|
||||
}
|
||||
|
||||
// test_executor
|
||||
|
||||
{
|
||||
error_code ec;
|
||||
stranded_socket<tcp, test_executor<>> s(
|
||||
test_executor<>(ioc.get_executor()), tcp::v4());
|
||||
|
||||
bool invoked;
|
||||
|
||||
invoked = false;
|
||||
s.async_read_some(net::mutable_buffer{},
|
||||
[&](error_code ec, std::size_t)
|
||||
{
|
||||
invoked = true;
|
||||
BEAST_EXPECTS(! ec, ec.message());
|
||||
});
|
||||
ioc.run();
|
||||
ioc.restart();
|
||||
BEAST_EXPECT(invoked);
|
||||
BEAST_EXPECT(s.get_executor()->total > 0);
|
||||
s.get_executor()->total = 0;
|
||||
|
||||
invoked = false;
|
||||
s.async_write_some(net::const_buffer{},
|
||||
[&](error_code ec, std::size_t)
|
||||
{
|
||||
invoked = true;
|
||||
BEAST_EXPECTS(! ec, ec.message());
|
||||
});
|
||||
ioc.run();
|
||||
ioc.restart();
|
||||
BEAST_EXPECT(invoked);
|
||||
BEAST_EXPECT(s.get_executor()->total > 0);
|
||||
s.get_executor()->total = 0;
|
||||
}
|
||||
|
||||
// bind_default_executor::asio_handler_invoke
|
||||
|
||||
#if 0
|
||||
// VFALCO This test fails, because it is unclear how
|
||||
// asio_handler_invoke interacts with the wrapper.
|
||||
// Need to ask Chris Kohlhoff about this one.
|
||||
{
|
||||
int flags = 0;
|
||||
net::post(
|
||||
ioc,
|
||||
detail::bind_default_executor(
|
||||
strand(ioc),
|
||||
test_handler{flags}));
|
||||
ioc.run();
|
||||
ioc.restart();
|
||||
BEAST_EXPECT(flags == 3);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
testJavadocs()
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
run()
|
||||
{
|
||||
testStream();
|
||||
testJavadocs();
|
||||
testMembers();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(beast,core,stranded_socket);
|
||||
|
||||
} // beast
|
||||
} // boost
|
@ -1,81 +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
|
||||
//
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include <boost/beast/core/stranded_stream.hpp>
|
||||
|
||||
#include "stream_tests.hpp"
|
||||
|
||||
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
|
||||
class stranded_stream_test
|
||||
: public beast::unit_test::suite
|
||||
{
|
||||
public:
|
||||
using tcp = net::ip::tcp;
|
||||
|
||||
void
|
||||
testStream()
|
||||
{
|
||||
net::io_context ioc;
|
||||
{
|
||||
using ex_t = net::io_context::executor_type;
|
||||
auto ex = ioc.get_executor();
|
||||
stranded_stream<tcp, ex_t> s1(ioc);
|
||||
stranded_stream<tcp, ex_t> s2(ex);
|
||||
stranded_stream<tcp, ex_t> s3(ioc, tcp::v4());
|
||||
stranded_stream<tcp, ex_t> s4(std::move(s1));
|
||||
s2.next_layer() = tcp::socket(ioc);
|
||||
BEAST_EXPECT(s1.get_executor() == ex);
|
||||
BEAST_EXPECT(s2.get_executor() == ex);
|
||||
BEAST_EXPECT(s3.get_executor() == ex);
|
||||
BEAST_EXPECT(s4.get_executor() == ex);
|
||||
}
|
||||
{
|
||||
using ex_t = net::io_context::strand;
|
||||
auto ex = ex_t{ioc};
|
||||
stranded_stream<tcp, ex_t> s1(ex);
|
||||
stranded_stream<tcp, ex_t> s2(ex, tcp::v4());
|
||||
stranded_stream<tcp, ex_t> s3(std::move(s1));
|
||||
s2.next_layer() = tcp::socket(ioc);
|
||||
BEAST_EXPECT(s1.get_executor() == ex);
|
||||
BEAST_EXPECT(s2.get_executor() == ex);
|
||||
BEAST_EXPECT(s3.get_executor() == ex);
|
||||
}
|
||||
{
|
||||
using ex_t = net::io_context::executor_type;
|
||||
test_sync_stream<stranded_stream<tcp, ex_t>>();
|
||||
test_async_stream<stranded_stream<tcp, ex_t>>();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testJavadocs()
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
run()
|
||||
{
|
||||
testStream();
|
||||
testJavadocs();
|
||||
pass();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(beast,core,stranded_stream);
|
||||
|
||||
} // beast
|
||||
} // boost
|
Reference in New Issue
Block a user