mirror of
https://github.com/boostorg/beast.git
synced 2025-07-30 12:57: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
|
* dynamic_buffer_ref tests and tidy
|
||||||
* flat_stream 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]
|
[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]
|
[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.
|
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
|
A timeout stream meets the requirements for synchronous and asynchronous
|
||||||
read and write streams by passing I/O through to an underlying
|
read and write streams by passing I/O through to an underlying
|
||||||
@ -131,4 +131,3 @@ streams:
|
|||||||
[code_core_3_layers_5]
|
[code_core_3_layers_5]
|
||||||
|
|
||||||
[endsect]
|
[endsect]
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@
|
|||||||
<member><link linkend="beast.ref.boost__beast__span">span</link></member>
|
<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__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__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_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__string_view">string_view</link></member>
|
||||||
<member><link linkend="beast.ref.boost__beast__timeout_stream">timeout_stream</link> <emphasis role="green">🞲</emphasis></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__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__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__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__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__get_lowest_layer">get_lowest_layer</link> <emphasis role="green">🞲</emphasis></member>
|
||||||
<member><link linkend="beast.ref.boost__beast__iequals">iequals</link></member>
|
<member><link linkend="beast.ref.boost__beast__iequals">iequals</link></member>
|
||||||
|
@ -39,6 +39,9 @@
|
|||||||
<xsl:when test="type = 'class EndpointSequence'">
|
<xsl:when test="type = 'class EndpointSequence'">
|
||||||
<xsl:text>class __EndpointSequence__</xsl:text>
|
<xsl:text>class __EndpointSequence__</xsl:text>
|
||||||
</xsl:when>
|
</xsl:when>
|
||||||
|
<xsl:when test="type = 'class ExecutionContext'">
|
||||||
|
<xsl:text>class __ExecutionContext__</xsl:text>
|
||||||
|
</xsl:when>
|
||||||
<xsl:when test="type = 'class Executor'">
|
<xsl:when test="type = 'class Executor'">
|
||||||
<xsl:text>class __Executor__</xsl:text>
|
<xsl:text>class __Executor__</xsl:text>
|
||||||
</xsl:when>
|
</xsl:when>
|
||||||
|
@ -41,7 +41,7 @@
|
|||||||
#include <boost/beast/core/span.hpp>
|
#include <boost/beast/core/span.hpp>
|
||||||
#include <boost/beast/core/static_buffer.hpp>
|
#include <boost/beast/core/static_buffer.hpp>
|
||||||
#include <boost/beast/core/static_string.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/stream_traits.hpp>
|
||||||
#include <boost/beast/core/string.hpp>
|
#include <boost/beast/core/string.hpp>
|
||||||
#include <boost/beast/core/string_param.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.
|
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,
|
The function object should return true if the next endpoint should be tried,
|
||||||
and false if it should be skipped.
|
and false if it should be skipped.
|
||||||
|
|
||||||
@param handler The handler to be called when the connect operation
|
@param handler The handler to be called when the connect operation
|
||||||
completes. Ownership of the handler may be transferred. The function
|
completes. Ownership of the handler may be transferred. The function
|
||||||
signature of the handler must be:
|
signature of the handler must be:
|
||||||
@ -701,7 +702,7 @@ async_connect(
|
|||||||
not, the handler will not be invoked from within this function. Invocation
|
not, the handler will not be invoked from within this function. Invocation
|
||||||
of the handler will be performed in a manner equivalent to using
|
of the handler will be performed in a manner equivalent to using
|
||||||
`net::io_context::post()`.
|
`net::io_context::post()`.
|
||||||
|
|
||||||
@par Example
|
@par Example
|
||||||
The following connect condition function object can be used to output
|
The following connect condition function object can be used to output
|
||||||
information about the individual connection attempts:
|
information about the individual connection attempts:
|
||||||
|
@ -7,8 +7,8 @@
|
|||||||
// Official repository: https://github.com/boostorg/beast
|
// Official repository: https://github.com/boostorg/beast
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef BOOST_BEAST_CORE_DETAIL_STRANDED_STREAM_HPP
|
#ifndef BOOST_BEAST_CORE_DETAIL_STRANDED_SOCKET_HPP
|
||||||
#define BOOST_BEAST_CORE_DETAIL_STRANDED_STREAM_HPP
|
#define BOOST_BEAST_CORE_DETAIL_STRANDED_SOCKET_HPP
|
||||||
|
|
||||||
#include <boost/beast/core/detail/bind_default_executor.hpp>
|
#include <boost/beast/core/detail/bind_default_executor.hpp>
|
||||||
#include <boost/asio/basic_stream_socket.hpp>
|
#include <boost/asio/basic_stream_socket.hpp>
|
||||||
@ -19,20 +19,20 @@ namespace beast {
|
|||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
template<class Protocol>
|
template<class Protocol>
|
||||||
class stranded_stream_base
|
class stranded_socket_base
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
net::basic_stream_socket<Protocol> socket_;
|
net::basic_stream_socket<Protocol> socket_;
|
||||||
|
|
||||||
template<class... Args>
|
template<class... Args>
|
||||||
explicit
|
explicit
|
||||||
stranded_stream_base(Args&&... args)
|
stranded_socket_base(Args&&... args)
|
||||||
: socket_(std::forward<Args>(args)...)
|
: socket_(std::forward<Args>(args)...)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
stranded_stream_base(stranded_stream_base&&) = default;
|
stranded_socket_base(stranded_socket_base&&) = default;
|
||||||
stranded_stream_base& operator=(stranded_stream_base&&) = default;
|
stranded_socket_base& operator=(stranded_socket_base&&) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // detail
|
} // 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
|
span.cpp
|
||||||
static_buffer.cpp
|
static_buffer.cpp
|
||||||
static_string.cpp
|
static_string.cpp
|
||||||
stranded_stream.cpp
|
stranded_socket.cpp
|
||||||
stream_traits.cpp
|
stream_traits.cpp
|
||||||
string.cpp
|
string.cpp
|
||||||
string_param.cpp
|
string_param.cpp
|
||||||
|
@ -49,7 +49,7 @@ local SOURCES =
|
|||||||
span.cpp
|
span.cpp
|
||||||
static_buffer.cpp
|
static_buffer.cpp
|
||||||
static_string.cpp
|
static_string.cpp
|
||||||
stranded_stream.cpp
|
stranded_socket.cpp
|
||||||
stream_traits.cpp
|
stream_traits.cpp
|
||||||
string.cpp
|
string.cpp
|
||||||
string_param.cpp
|
string_param.cpp
|
||||||
|
@ -134,7 +134,7 @@ public:
|
|||||||
{
|
{
|
||||||
// shouldn't be called since the enclosing
|
// shouldn't be called since the enclosing
|
||||||
// networking wrapper only uses dispatch
|
// networking wrapper only uses dispatch
|
||||||
s_.fail("unexpected post", __FILE__, __LINE__);
|
BEAST_FAIL();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class F, class Alloc>
|
template<class F, class Alloc>
|
||||||
@ -142,7 +142,7 @@ public:
|
|||||||
{
|
{
|
||||||
// shouldn't be called since the enclosing
|
// shouldn't be called since the enclosing
|
||||||
// networking wrapper only uses dispatch
|
// 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