Add teardown_role for correct TIME_WAIT behavior (API Change):

* teardown_tag is replaced with teardown_role, a client/server
  flag used to determine whether the shutdown is performed
  before or after reading the EOF. This is in accordance with
  RFC6455 7.1.1:

  https://tools.ietf.org/html/rfc6455#section-7.1.1

Actions Required:

* Modify signatures of teardown and async_teardown to use
  teardown_role instead of teardown_tag

* Change calls to teardown and async_teardown to pass the
  correct role: client or server depending on context.
This commit is contained in:
Vinnie Falco
2017-08-04 13:31:24 -07:00
parent de03a1a32d
commit 60c8a560bf
19 changed files with 254 additions and 157 deletions

View File

@ -23,6 +23,8 @@ API Changes:
* drain_buffer is removed * drain_buffer is removed
* role_type replaces teardown_tag
Actions Required: Actions Required:
* Remove calling code which drains the connection after * Remove calling code which drains the connection after
@ -32,6 +34,12 @@ Actions Required:
it is no longer necessary to manually drain the connection it is no longer necessary to manually drain the connection
after closing. after closing.
* Modify signatures of teardown and async_teardown to use
role_type instead of teardown_tag
* Change calls to teardown and async_teardown to pass the
correct role_type, client or server, depending on context.
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
Version 99: Version 99:

View File

@ -147,6 +147,7 @@
<member><link linkend="beast.ref.boost__beast__websocket__close_code">close_code</link></member> <member><link linkend="beast.ref.boost__beast__websocket__close_code">close_code</link></member>
<member><link linkend="beast.ref.boost__beast__websocket__error">error</link></member> <member><link linkend="beast.ref.boost__beast__websocket__error">error</link></member>
<member><link linkend="beast.ref.boost__beast__websocket__frame_type">frame_type</link></member> <member><link linkend="beast.ref.boost__beast__websocket__frame_type">frame_type</link></member>
<member><link linkend="beast.ref.boost__beast__websocket__role_type">role_type</link></member>
</simplelist> </simplelist>
</entry> </entry>
</row> </row>

View File

@ -294,14 +294,14 @@ public:
template<class SyncStream> template<class SyncStream>
friend friend
void void
teardown(boost::beast::websocket::teardown_tag, teardown(boost::beast::websocket::role_type,
ssl_stream<SyncStream>& stream, ssl_stream<SyncStream>& stream,
boost::system::error_code& ec); boost::system::error_code& ec);
template<class AsyncStream, class TeardownHandler> template<class AsyncStream, class TeardownHandler>
friend friend
void void
async_teardown(boost::beast::websocket::teardown_tag, async_teardown(boost::beast::websocket::role_type,
ssl_stream<AsyncStream>& stream, TeardownHandler&& handler); ssl_stream<AsyncStream>& stream, TeardownHandler&& handler);
}; };
@ -312,24 +312,27 @@ public:
template<class SyncStream> template<class SyncStream>
inline inline
void void
teardown(boost::beast::websocket::teardown_tag, teardown(
boost::beast::websocket::role_type role,
ssl_stream<SyncStream>& stream, ssl_stream<SyncStream>& stream,
boost::system::error_code& ec) boost::system::error_code& ec)
{ {
// Just forward it to the wrapped ssl::stream // Just forward it to the wrapped ssl::stream
using boost::beast::websocket::teardown; using boost::beast::websocket::teardown;
teardown(boost::beast::websocket::teardown_tag{}, *stream.p_, ec); teardown(role, *stream.p_, ec);
} }
template<class AsyncStream, class TeardownHandler> template<class AsyncStream, class TeardownHandler>
inline inline
void void
async_teardown(boost::beast::websocket::teardown_tag, async_teardown(
ssl_stream<AsyncStream>& stream, TeardownHandler&& handler) boost::beast::websocket::role_type role,
ssl_stream<AsyncStream>& stream,
TeardownHandler&& handler)
{ {
// Just forward it to the wrapped ssl::stream // Just forward it to the wrapped ssl::stream
using boost::beast::websocket::async_teardown; using boost::beast::websocket::async_teardown;
async_teardown(boost::beast::websocket::teardown_tag{}, async_teardown(role,
*stream.p_, std::forward<TeardownHandler>(handler)); *stream.p_, std::forward<TeardownHandler>(handler));
} }

View File

@ -180,7 +180,8 @@ operator()(error_code ec, std::size_t)
go_teardown: go_teardown:
BOOST_ASSERT(ws_.wr_block_ == tok_); BOOST_ASSERT(ws_.wr_block_ == tok_);
step_ = do_teardown + 1; step_ = do_teardown + 1;
websocket_helpers::call_async_teardown( using beast::websocket::async_teardown;
async_teardown(ws_.role_,
ws_.stream_, std::move(*this)); ws_.stream_, std::move(*this));
return; return;
@ -234,7 +235,8 @@ do_fail(
if(failed_) if(failed_)
return; return;
} }
websocket_helpers::call_teardown(stream_, ec); using beast::websocket::teardown;
teardown(role_, stream_, ec);
if(ec == boost::asio::error::eof) if(ec == boost::asio::error::eof)
{ {
// Rationale: // Rationale:

View File

@ -33,20 +33,25 @@ Behavior of ssl::stream regarding close_
template<class AsyncStream> template<class AsyncStream>
void void
teardown(teardown_tag, teardown(
role_type,
boost::asio::ssl::stream<AsyncStream>& stream, boost::asio::ssl::stream<AsyncStream>& stream,
error_code& ec) error_code& ec)
{ {
stream.shutdown(ec); stream.shutdown(ec);
} }
template<class AsyncStream, class TeardownHandler> template<
class AsyncStream,
class TeardownHandler>
void void
async_teardown(teardown_tag, async_teardown(
role_type,
boost::asio::ssl::stream<AsyncStream>& stream, boost::asio::ssl::stream<AsyncStream>& stream,
TeardownHandler&& handler) TeardownHandler&& handler)
{ {
stream.async_shutdown(std::forward<TeardownHandler>(handler)); stream.async_shutdown(
std::forward<TeardownHandler>(handler));
} }
} // websocket } // websocket

View File

@ -10,8 +10,7 @@
#ifndef BOOST_BEAST_WEBSOCKET_IMPL_TEARDOWN_IPP #ifndef BOOST_BEAST_WEBSOCKET_IMPL_TEARDOWN_IPP
#define BOOST_BEAST_WEBSOCKET_IMPL_TEARDOWN_IPP #define BOOST_BEAST_WEBSOCKET_IMPL_TEARDOWN_IPP
#include <boost/beast/core/async_result.hpp> #include <boost/beast/core/bind_handler.hpp>
#include <boost/beast/core/handler_ptr.hpp>
#include <boost/beast/core/type_traits.hpp> #include <boost/beast/core/type_traits.hpp>
#include <boost/asio/handler_alloc_hook.hpp> #include <boost/asio/handler_alloc_hook.hpp>
#include <boost/asio/handler_continuation_hook.hpp> #include <boost/asio/handler_continuation_hook.hpp>
@ -30,35 +29,30 @@ class teardown_tcp_op
using socket_type = using socket_type =
boost::asio::ip::tcp::socket; boost::asio::ip::tcp::socket;
struct data Handler h_;
{ socket_type& s_;
bool cont; role_type role_;
socket_type& socket; int step_ = 0;
char buf[2048];
int state = 0;
data(Handler& handler, socket_type& socket_)
: socket(socket_)
{
using boost::asio::asio_handler_is_continuation;
cont = asio_handler_is_continuation(std::addressof(handler));
}
};
handler_ptr<data, Handler> d_;
public: public:
teardown_tcp_op(teardown_tcp_op&& other) = default;
teardown_tcp_op(teardown_tcp_op const& other) = default;
template<class DeducedHandler> template<class DeducedHandler>
teardown_tcp_op( teardown_tcp_op(
DeducedHandler&& h, DeducedHandler&& h,
socket_type& socket) socket_type& s,
: d_(std::forward<DeducedHandler>(h), socket) role_type role)
: h_(std::forward<DeducedHandler>(h))
, s_(s)
, role_(role)
{ {
(*this)(error_code{}, 0, false);
} }
void void
operator()(error_code ec, std::size_t, bool again = true); operator()(
error_code ec = {},
std::size_t bytes_transferred = 0);
friend friend
void* asio_handler_allocate(std::size_t size, void* asio_handler_allocate(std::size_t size,
@ -66,7 +60,7 @@ public:
{ {
using boost::asio::asio_handler_allocate; using boost::asio::asio_handler_allocate;
return asio_handler_allocate( return asio_handler_allocate(
size, std::addressof(op->d_.handler())); size, std::addressof(op->h_));
} }
friend friend
@ -75,13 +69,15 @@ public:
{ {
using boost::asio::asio_handler_deallocate; using boost::asio::asio_handler_deallocate;
asio_handler_deallocate( asio_handler_deallocate(
p, size, std::addressof(op->d_.handler())); p, size, std::addressof(op->h_));
} }
friend friend
bool asio_handler_is_continuation(teardown_tcp_op* op) bool asio_handler_is_continuation(teardown_tcp_op* op)
{ {
return op->d_->cont; using boost::asio::asio_handler_is_continuation;
return op->step_ >= 3 ||
asio_handler_is_continuation(std::addressof(op->h_));
} }
template<class Function> template<class Function>
@ -91,40 +87,58 @@ public:
{ {
using boost::asio::asio_handler_invoke; using boost::asio::asio_handler_invoke;
asio_handler_invoke( asio_handler_invoke(
f, std::addressof(op->d_.handler())); f, std::addressof(op->h_));
} }
}; };
template<class Handler> template<class Handler>
void void
teardown_tcp_op<Handler>:: teardown_tcp_op<Handler>::
operator()(error_code ec, std::size_t, bool again) operator()(error_code ec, std::size_t)
{ {
using boost::asio::buffer; using boost::asio::buffer;
auto& d = *d_; using tcp = boost::asio::ip::tcp;
d.cont = d.cont || again; switch(step_)
while(! ec)
{ {
switch(d.state) case 0:
s_.non_blocking(true, ec);
if(ec)
{ {
case 0: step_ = 1;
d.state = 1; return s_.get_io_service().post(
d.socket.shutdown( bind_handler(std::move(*this), ec, 0));
boost::asio::ip::tcp::socket::shutdown_send, ec);
break;
case 1:
d.socket.async_read_some(
buffer(d.buf), std::move(*this));
return;
} }
step_ = 2;
if(role_ == role_type::server)
s_.shutdown(tcp::socket::shutdown_send, ec);
goto do_read;
case 1:
break;
case 2:
step_ = 3;
case 3:
if(ec != boost::asio::error::would_block)
break;
{
char buf[2048];
s_.read_some(
boost::asio::buffer(buf), ec);
if(ec)
break;
}
do_read:
return s_.async_read_some(
boost::asio::null_buffers{},
std::move(*this));
} }
if(ec == boost::asio::error::eof) if(role_ == role_type::client)
{ s_.shutdown(tcp::socket::shutdown_send, ec);
d.socket.close(ec); s_.close(ec);
ec = error_code{}; h_(ec);
}
d_.invoke(ec);
} }
} // detail } // detail
@ -133,13 +147,15 @@ operator()(error_code ec, std::size_t, bool again)
inline inline
void void
teardown(teardown_tag, teardown(
role_type role,
boost::asio::ip::tcp::socket& socket, boost::asio::ip::tcp::socket& socket,
error_code& ec) error_code& ec)
{ {
using boost::asio::buffer; using boost::asio::buffer;
socket.shutdown( if(role == role_type::server)
boost::asio::ip::tcp::socket::shutdown_send, ec); socket.shutdown(
boost::asio::ip::tcp::socket::shutdown_send, ec);
while(! ec) while(! ec)
{ {
char buf[8192]; char buf[8192];
@ -148,24 +164,27 @@ teardown(teardown_tag,
if(! n) if(! n)
break; break;
} }
if(ec == boost::asio::error::eof) if(role == role_type::client)
ec = error_code{}; socket.shutdown(
boost::asio::ip::tcp::socket::shutdown_send, ec);
socket.close(ec); socket.close(ec);
} }
template<class TeardownHandler> template<class TeardownHandler>
inline inline
void void
async_teardown(teardown_tag, async_teardown(
role_type role,
boost::asio::ip::tcp::socket& socket, boost::asio::ip::tcp::socket& socket,
TeardownHandler&& handler) TeardownHandler&& handler)
{ {
static_assert(beast::is_completion_handler< static_assert(beast::is_completion_handler<
TeardownHandler, void(error_code)>::value, TeardownHandler, void(error_code)>::value,
"TeardownHandler requirements not met"); "TeardownHandler requirements not met");
detail::teardown_tcp_op<typename std::decay< detail::teardown_tcp_op<typename std::decay<
TeardownHandler>::type>{std::forward< TeardownHandler>::type>{std::forward<
TeardownHandler>(handler), socket}; TeardownHandler>(handler), socket,
role}();
} }
} // websocket } // websocket

View File

@ -0,0 +1,59 @@
//
// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// Official repository: https://github.com/boostorg/beast
//
#ifndef BOOST_BEAST_WEBSOCKET_ROLE_HPP
#define BOOST_BEAST_WEBSOCKET_ROLE_HPP
#include <boost/beast/config.hpp>
namespace boost {
namespace beast {
namespace websocket {
/** The role of the websocket stream endpoint.
Whether the endpoint is a client or server affects the
behavior of the <em>Close the WebSocket Connection</em>
operation described in rfc6455 section 7.1.1.
The shutdown behavior depends on the type of the next
layer template parameter used to construct the @ref stream.
Other next layer types including user-defined types
may implement different role-based behavior when
performing the close operation.
The default implementation for @ref stream when the next
layer type is a `boost::asio::ip::tcp::socket` behaves
as follows:
@li In the client role, a TCP/IP shutdown is sent after
reading all remaining data on the connection.
@li In the server role, a TCP/IP shutdown is sent before
reading all remaining data on the connection.
When the next layer type is a `boost::asio::ssl::stream`,
the connection is closed by performing the SSL closing
handshake corresponding to the role type, client or server.
@see https://tools.ietf.org/html/rfc6455#section-7.1.1
*/
enum class role_type
{
/// The stream is operating as a client.
client,
/// The stream is operating as a server.
server
};
} // websocket
} // beast
} // boost
#endif

View File

@ -28,15 +28,18 @@ namespace websocket {
`boost::asio::ssl::stream`, callers are responsible for `boost::asio::ssl::stream`, callers are responsible for
providing a suitable overload of this function. providing a suitable overload of this function.
@param role The role of the local endpoint
@param stream The stream to tear down. @param stream The stream to tear down.
@param ec Set to the error if any occurred. @param ec Set to the error if any occurred.
*/ */
template<class SyncStream> template<class SyncStream>
void void
teardown(teardown_tag, teardown(
role_type role,
boost::asio::ssl::stream<SyncStream>& stream, boost::asio::ssl::stream<SyncStream>& stream,
error_code& ec); error_code& ec);
/** Start tearing down a `boost::asio::ssl::stream`. /** Start tearing down a `boost::asio::ssl::stream`.
@ -48,6 +51,8 @@ teardown(teardown_tag,
callers are responsible for providing a suitable overload callers are responsible for providing a suitable overload
of this function. of this function.
@param role The role of the local endpoint
@param stream The stream to tear down. @param stream The stream to tear down.
@param handler The handler to be called when the request completes. @param handler The handler to be called when the request completes.
@ -65,9 +70,10 @@ teardown(teardown_tag,
template<class AsyncStream, class TeardownHandler> template<class AsyncStream, class TeardownHandler>
inline inline
void void
async_teardown(teardown_tag, async_teardown(
role_type role,
boost::asio::ssl::stream<AsyncStream>& stream, boost::asio::ssl::stream<AsyncStream>& stream,
TeardownHandler&& handler); TeardownHandler&& handler);
} // websocket } // websocket
} // beast } // beast

View File

@ -13,6 +13,7 @@
#include <boost/beast/config.hpp> #include <boost/beast/config.hpp>
#include <boost/beast/websocket/error.hpp> #include <boost/beast/websocket/error.hpp>
#include <boost/beast/websocket/option.hpp> #include <boost/beast/websocket/option.hpp>
#include <boost/beast/websocket/role.hpp>
#include <boost/beast/websocket/rfc6455.hpp> #include <boost/beast/websocket/rfc6455.hpp>
#include <boost/beast/websocket/detail/frame.hpp> #include <boost/beast/websocket/detail/frame.hpp>
#include <boost/beast/websocket/detail/hybi13.hpp> #include <boost/beast/websocket/detail/hybi13.hpp>
@ -145,16 +146,6 @@ class stream
using control_cb_type = using control_cb_type =
std::function<void(frame_type, string_view)>; std::function<void(frame_type, string_view)>;
/// Identifies the role of a WebSockets stream.
enum class role_type
{
/// Stream is operating as a client.
client,
/// Stream is operating as a server.
server
};
// State information for the message being received // State information for the message being received
// //
struct rd_t struct rd_t

View File

@ -11,7 +11,8 @@
#define BOOST_BEAST_WEBSOCKET_TEARDOWN_HPP #define BOOST_BEAST_WEBSOCKET_TEARDOWN_HPP
#include <boost/beast/config.hpp> #include <boost/beast/config.hpp>
#include <boost/beast/websocket/error.hpp> #include <boost/beast/core/error.hpp>
#include <boost/beast/websocket/role.hpp>
#include <boost/asio/ip/tcp.hpp> #include <boost/asio/ip/tcp.hpp>
#include <type_traits> #include <type_traits>
@ -19,15 +20,6 @@ namespace boost {
namespace beast { namespace beast {
namespace websocket { namespace websocket {
/** Tag type used to find @ref beast::websocket::teardown and @ref beast::websocket::async_teardown overloads
Overloads of @ref beast::websocket::teardown and
@ref beast::websocket::async_teardown for user defined types
must take a value of type @ref teardown_tag in the first
argument in order to be found by the implementation.
*/
struct teardown_tag {};
/** Tear down a connection. /** Tear down a connection.
This tears down a connection. The implementation will call This tears down a connection. The implementation will call
@ -37,13 +29,18 @@ struct teardown_tag {};
`boost::asio::ssl::stream`, callers are responsible for `boost::asio::ssl::stream`, callers are responsible for
providing a suitable overload of this function. providing a suitable overload of this function.
@param role The role of the local endpoint
@param socket The socket to tear down. @param socket The socket to tear down.
@param ec Set to the error if any occurred. @param ec Set to the error if any occurred.
*/ */
template<class Socket> template<class Socket>
void void
teardown(teardown_tag, Socket& socket, error_code& ec) teardown(
role_type role,
Socket& socket,
error_code& ec)
{ {
/* /*
If you are trying to use OpenSSL and this goes off, you need to If you are trying to use OpenSSL and this goes off, you need to
@ -51,7 +48,7 @@ teardown(teardown_tag, Socket& socket, error_code& ec)
If you are creating an instance of beast::websocket::stream with your If you are creating an instance of beast::websocket::stream with your
own user defined type, you must provide an overload of teardown with own user defined type, you must provide an overload of teardown with
the corresponding signature (including the teardown_tag). the corresponding signature (including the role_type).
*/ */
static_assert(sizeof(Socket)==-1, static_assert(sizeof(Socket)==-1,
"Unknown Socket type in teardown."); "Unknown Socket type in teardown.");
@ -67,6 +64,8 @@ teardown(teardown_tag, Socket& socket, error_code& ec)
callers are responsible for providing a suitable overload callers are responsible for providing a suitable overload
of this function. of this function.
@param role The role of the local endpoint
@param socket The socket to tear down. @param socket The socket to tear down.
@param handler The handler to be called when the request completes. @param handler The handler to be called when the request completes.
@ -82,9 +81,14 @@ teardown(teardown_tag, Socket& socket, error_code& ec)
manner equivalent to using boost::asio::io_service::post(). manner equivalent to using boost::asio::io_service::post().
*/ */
template<class Socket, class TeardownHandler> template<
class Socket,
class TeardownHandler>
void void
async_teardown(teardown_tag, Socket& socket, TeardownHandler&& handler) async_teardown(
role_type role,
Socket& socket,
TeardownHandler&& handler)
{ {
/* /*
If you are trying to use OpenSSL and this goes off, you need to If you are trying to use OpenSSL and this goes off, you need to
@ -92,7 +96,7 @@ async_teardown(teardown_tag, Socket& socket, TeardownHandler&& handler)
If you are creating an instance of beast::websocket::stream with your If you are creating an instance of beast::websocket::stream with your
own user defined type, you must provide an overload of teardown with own user defined type, you must provide an overload of teardown with
the corresponding signature (including the teardown_tag). the corresponding signature (including the role_type).
*/ */
static_assert(sizeof(Socket)==-1, static_assert(sizeof(Socket)==-1,
"Unknown Socket type in async_teardown."); "Unknown Socket type in async_teardown.");
@ -102,36 +106,6 @@ async_teardown(teardown_tag, Socket& socket, TeardownHandler&& handler)
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
namespace websocket_helpers {
// Calls to teardown and async_teardown must be made from
// a namespace that does not contain any overloads of these
// functions. The websocket_helpers namespace is defined here
// for that purpose.
template<class Socket>
inline
void
call_teardown(Socket& socket, error_code& ec)
{
using websocket::teardown;
teardown(websocket::teardown_tag{}, socket, ec);
}
template<class Socket, class TeardownHandler>
inline
void
call_async_teardown(Socket& socket, TeardownHandler&& handler)
{
using websocket::async_teardown;
async_teardown(websocket::teardown_tag{}, socket,
std::forward<TeardownHandler>(handler));
}
} // websocket_helpers
//------------------------------------------------------------------------------
namespace websocket { namespace websocket {
/** Tear down a `boost::asio::ip::tcp::socket`. /** Tear down a `boost::asio::ip::tcp::socket`.
@ -143,13 +117,17 @@ namespace websocket {
`boost::asio::ssl::stream`, callers are responsible for `boost::asio::ssl::stream`, callers are responsible for
providing a suitable overload of this function. providing a suitable overload of this function.
@param role The role of the local endpoint
@param socket The socket to tear down. @param socket The socket to tear down.
@param ec Set to the error if any occurred. @param ec Set to the error if any occurred.
*/ */
void void
teardown(teardown_tag, teardown(
boost::asio::ip::tcp::socket& socket, error_code& ec); role_type role,
boost::asio::ip::tcp::socket& socket,
error_code& ec);
/** Start tearing down a `boost::asio::ip::tcp::socket`. /** Start tearing down a `boost::asio::ip::tcp::socket`.
@ -161,6 +139,8 @@ teardown(teardown_tag,
callers are responsible for providing a suitable overload callers are responsible for providing a suitable overload
of this function. of this function.
@param role The role of the local endpoint
@param socket The socket to tear down. @param socket The socket to tear down.
@param handler The handler to be called when the request completes. @param handler The handler to be called when the request completes.
@ -178,8 +158,10 @@ teardown(teardown_tag,
*/ */
template<class TeardownHandler> template<class TeardownHandler>
void void
async_teardown(teardown_tag, async_teardown(
boost::asio::ip::tcp::socket& socket, TeardownHandler&& handler); role_type role,
boost::asio::ip::tcp::socket& socket,
TeardownHandler&& handler);
} // websocket } // websocket
} // beast } // beast

View File

@ -21,6 +21,7 @@ add_executable (tests-beast-websocket
error.cpp error.cpp
option.cpp option.cpp
rfc6455.cpp rfc6455.cpp
role.cpp
stream.cpp stream.cpp
teardown.cpp teardown.cpp
frame.cpp frame.cpp

View File

@ -15,6 +15,7 @@ local SOURCES =
teardown.cpp teardown.cpp
frame.cpp frame.cpp
mask.cpp mask.cpp
role.cpp
utf8_checker.cpp utf8_checker.cpp
; ;

View File

@ -0,0 +1,11 @@
//
// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// Official repository: https://github.com/boostorg/beast
//
// Test that header file is self-contained.
#include <boost/beast/websocket/role.hpp>

View File

@ -161,21 +161,24 @@ public:
friend friend
void void
teardown(websocket::teardown_tag, teardown(
websocket::role_type role,
fail_stream<NextLayer>& stream, fail_stream<NextLayer>& stream,
boost::system::error_code& ec) boost::system::error_code& ec)
{ {
if(stream.pfc_->fail(ec)) if(stream.pfc_->fail(ec))
return; return;
beast::websocket_helpers::call_teardown(stream.next_layer(), ec); using beast::websocket::teardown;
teardown(role, stream.next_layer(), ec);
} }
template<class TeardownHandler> template<class TeardownHandler>
friend friend
void void
async_teardown(websocket::teardown_tag, async_teardown(
websocket::role_type role,
fail_stream<NextLayer>& stream, fail_stream<NextLayer>& stream,
TeardownHandler&& handler) TeardownHandler&& handler)
{ {
error_code ec; error_code ec;
if(stream.pfc_->fail(ec)) if(stream.pfc_->fail(ec))
@ -184,8 +187,9 @@ public:
bind_handler(std::move(handler), ec)); bind_handler(std::move(handler), ec));
return; return;
} }
beast::websocket_helpers::call_async_teardown( using beast::websocket::async_teardown;
stream.next_layer(), std::forward<TeardownHandler>(handler)); async_teardown(role, stream.next_layer(),
std::forward<TeardownHandler>(handler));
} }
}; };

View File

@ -197,13 +197,15 @@ public:
friend friend
void void
teardown(websocket::teardown_tag, teardown(
websocket::role_type role,
stream& s, boost::system::error_code& ec); stream& s, boost::system::error_code& ec);
template<class TeardownHandler> template<class TeardownHandler>
friend friend
void void
async_teardown(websocket::teardown_tag, async_teardown(
websocket::role_type,
stream& s, TeardownHandler&& handler); stream& s, TeardownHandler&& handler);
}; };
@ -229,8 +231,10 @@ public:
inline inline
void void
teardown(websocket::teardown_tag, teardown(
pipe::stream& s, boost::system::error_code& ec) websocket::role_type,
pipe::stream& s,
boost::system::error_code& ec)
{ {
if(s.fc_) if(s.fc_)
{ {
@ -247,7 +251,7 @@ teardown(websocket::teardown_tag,
template<class TeardownHandler> template<class TeardownHandler>
inline inline
void void
async_teardown(websocket::teardown_tag, async_teardown(websocket::role_type,
pipe::stream& s, TeardownHandler&& handler) pipe::stream& s, TeardownHandler&& handler)
{ {
error_code ec; error_code ec;

View File

@ -440,13 +440,13 @@ public:
friend friend
void void
teardown(websocket::teardown_tag, teardown(websocket::role_type,
stream& s, boost::system::error_code& ec); stream& s, boost::system::error_code& ec);
template<class TeardownHandler> template<class TeardownHandler>
friend friend
void void
async_teardown(websocket::teardown_tag, async_teardown(websocket::role_type role,
stream& s, TeardownHandler&& handler); stream& s, TeardownHandler&& handler);
}; };
@ -654,7 +654,7 @@ async_write_some(ConstBufferSequence const& buffers,
inline inline
void void
teardown(websocket::teardown_tag, teardown(websocket::role_type,
stream& s, boost::system::error_code& ec) stream& s, boost::system::error_code& ec)
{ {
if(s.in_.fc) if(s.in_.fc)
@ -672,7 +672,7 @@ teardown(websocket::teardown_tag,
template<class TeardownHandler> template<class TeardownHandler>
inline inline
void void
async_teardown(websocket::teardown_tag, async_teardown(websocket::role_type,
stream& s, TeardownHandler&& handler) stream& s, TeardownHandler&& handler)
{ {
error_code ec; error_code ec;

View File

@ -150,7 +150,7 @@ public:
friend friend
void void
teardown(websocket::teardown_tag, teardown(websocket::role_type,
string_iostream&, string_iostream&,
boost::system::error_code& ec) boost::system::error_code& ec)
{ {
@ -160,7 +160,7 @@ public:
template<class TeardownHandler> template<class TeardownHandler>
friend friend
void void
async_teardown(websocket::teardown_tag, async_teardown(websocket::role_type,
string_iostream& stream, string_iostream& stream,
TeardownHandler&& handler) TeardownHandler&& handler)
{ {

View File

@ -138,7 +138,7 @@ public:
friend friend
void void
teardown(websocket::teardown_tag, teardown(websocket::role_type,
string_istream&, string_istream&,
boost::system::error_code& ec) boost::system::error_code& ec)
{ {
@ -148,7 +148,7 @@ public:
template<class TeardownHandler> template<class TeardownHandler>
friend friend
void void
async_teardown(websocket::teardown_tag, async_teardown(websocket::role_type,
string_istream& stream, string_istream& stream,
TeardownHandler&& handler) TeardownHandler&& handler)
{ {

View File

@ -126,7 +126,7 @@ public:
friend friend
void void
teardown(websocket::teardown_tag, teardown(websocket::role_type,
string_ostream&, string_ostream&,
boost::system::error_code& ec) boost::system::error_code& ec)
{ {
@ -136,7 +136,7 @@ public:
template<class TeardownHandler> template<class TeardownHandler>
friend friend
void void
async_teardown(websocket::teardown_tag, async_teardown(websocket::role_type,
string_ostream& stream, string_ostream& stream,
TeardownHandler&& handler) TeardownHandler&& handler)
{ {