mirror of
https://github.com/boostorg/beast.git
synced 2025-07-31 05:17:26 +02:00
Refactor fail/clode code
This commit is contained in:
@ -10,6 +10,7 @@ Version 100:
|
||||
WebSocket:
|
||||
|
||||
* Remove obsolete frame tests
|
||||
* Refactor fail/clode code
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
@ -39,7 +39,8 @@ class stream<NextLayer>::fail_op
|
||||
stream<NextLayer>& ws_;
|
||||
int step_ = 0;
|
||||
bool dispatched_ = false;
|
||||
fail_how how_;
|
||||
close_code code_;
|
||||
error_code ev_;
|
||||
token tok_;
|
||||
|
||||
public:
|
||||
@ -51,27 +52,12 @@ public:
|
||||
fail_op(
|
||||
DeducedHandler&& h,
|
||||
stream<NextLayer>& ws,
|
||||
close_code code)
|
||||
close_code code,
|
||||
error_code ev)
|
||||
: h_(std::forward<DeducedHandler>(h))
|
||||
, ws_(ws)
|
||||
, how_(fail_how::code)
|
||||
, tok_(ws_.t_.unique())
|
||||
{
|
||||
ws_.rd_.fb.consume(ws_.rd_.fb.size());
|
||||
ws_.template write_close<
|
||||
flat_static_buffer_base>(
|
||||
ws_.rd_.fb, code);
|
||||
}
|
||||
|
||||
// maybe send frame in fb, then teardown
|
||||
template<class DeducedHandler>
|
||||
fail_op(
|
||||
DeducedHandler&& h,
|
||||
stream<NextLayer>& ws,
|
||||
fail_how how)
|
||||
: h_(std::forward<DeducedHandler>(h))
|
||||
, ws_(ws)
|
||||
, how_(how)
|
||||
, code_(code)
|
||||
, ev_(ev)
|
||||
, tok_(ws_.t_.unique())
|
||||
{
|
||||
}
|
||||
@ -168,12 +154,16 @@ operator()(error_code ec, std::size_t)
|
||||
ec = boost::asio::error::operation_aborted;
|
||||
break;
|
||||
}
|
||||
if(how_ == fail_how::teardown)
|
||||
if(code_ == close_code::none)
|
||||
goto go_teardown;
|
||||
if(ws_.wr_close_)
|
||||
goto go_teardown;
|
||||
// send close frame
|
||||
step_ = do_teardown;
|
||||
ws_.rd_.fb.consume(ws_.rd_.fb.size());
|
||||
ws_.template write_close<
|
||||
flat_static_buffer_base>(
|
||||
ws_.rd_.fb, code_);
|
||||
ws_.wr_close_ = true;
|
||||
return boost::asio::async_write(
|
||||
ws_.stream_, ws_.rd_.fb.data(),
|
||||
@ -192,13 +182,12 @@ operator()(error_code ec, std::size_t)
|
||||
BOOST_ASSERT(ws_.wr_block_ == tok_);
|
||||
step_ = do_teardown + 1;
|
||||
websocket_helpers::call_async_teardown(
|
||||
ws_.next_layer(), std::move(*this));
|
||||
ws_.stream_, std::move(*this));
|
||||
return;
|
||||
|
||||
case do_teardown + 1:
|
||||
BOOST_ASSERT(ws_.wr_block_ == tok_);
|
||||
dispatched_ = true;
|
||||
ws_.failed_ = true;
|
||||
ws_.wr_block_.reset();
|
||||
if(ec == boost::asio::error::eof)
|
||||
{
|
||||
@ -207,15 +196,8 @@ operator()(error_code ec, std::size_t)
|
||||
ec.assign(0, ec.category());
|
||||
}
|
||||
if(! ec)
|
||||
{
|
||||
switch(how_)
|
||||
{
|
||||
default:
|
||||
case fail_how::code:
|
||||
case fail_how::teardown: ec = error::failed; break;
|
||||
case fail_how::close: ec = error::closed; break;
|
||||
}
|
||||
}
|
||||
ec = ev_;
|
||||
ws_.failed_ = true;
|
||||
break;
|
||||
}
|
||||
// upcall
|
||||
@ -230,6 +212,61 @@ operator()(error_code ec, std::size_t)
|
||||
h_(ec, 0);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/* _Fail the WebSocket Connection_
|
||||
*/
|
||||
template<class NextLayer>
|
||||
void
|
||||
stream<NextLayer>::
|
||||
do_fail(
|
||||
close_code code, // if set, send a close frame first
|
||||
error_code ev, // error code to use upon success
|
||||
error_code& ec) // set to the error, else set to ev
|
||||
{
|
||||
BOOST_ASSERT(ev);
|
||||
if(code != close_code::none && ! wr_close_)
|
||||
{
|
||||
wr_close_ = true;
|
||||
detail::frame_streambuf fb;
|
||||
write_close<flat_static_buffer_base>(fb, code);
|
||||
boost::asio::write(stream_, fb.data(), ec);
|
||||
failed_ = !!ec;
|
||||
if(failed_)
|
||||
return;
|
||||
}
|
||||
websocket_helpers::call_teardown(stream_, ec);
|
||||
if(ec == boost::asio::error::eof)
|
||||
{
|
||||
// Rationale:
|
||||
// http://stackoverflow.com/questions/25587403/boost-asio-ssl-async-shutdown-always-finishes-with-an-error
|
||||
ec.assign(0, ec.category());
|
||||
}
|
||||
failed_ = !!ec;
|
||||
if(failed_)
|
||||
return;
|
||||
ec = ev;
|
||||
failed_ = true;
|
||||
}
|
||||
|
||||
/* _Fail the WebSocket Connection_
|
||||
*/
|
||||
template<class NextLayer>
|
||||
template<class Handler>
|
||||
void
|
||||
stream<NextLayer>::
|
||||
do_async_fail(
|
||||
close_code code, // if set, send a close frame first
|
||||
error_code ev, // error code to use upon success
|
||||
Handler&& handler)
|
||||
{
|
||||
fail_op<typename std::decay<Handler>::type>{
|
||||
std::forward<Handler>(handler),
|
||||
*this,
|
||||
code,
|
||||
ev}();
|
||||
}
|
||||
|
||||
} // websocket
|
||||
} // beast
|
||||
} // boost
|
||||
|
@ -155,7 +155,7 @@ operator()(error_code ec, bool again)
|
||||
// got response
|
||||
case 2:
|
||||
{
|
||||
d.ws.do_response(d.res, d.key, ec);
|
||||
d.ws.on_response(d.res, d.key, ec);
|
||||
// call handler
|
||||
d.state = 99;
|
||||
break;
|
||||
@ -416,7 +416,7 @@ do_handshake(
|
||||
http::read(next_layer(), rd_.buf, res, ec);
|
||||
if(ec)
|
||||
return;
|
||||
do_response(res, key, ec);
|
||||
on_response(res, key, ec);
|
||||
if(res_p)
|
||||
*res_p = std::move(res);
|
||||
}
|
||||
|
@ -139,11 +139,9 @@ operator()(
|
||||
if(! ws_.parse_fh(ws_.rd_.fh, ws_.rd_.buf, code))
|
||||
{
|
||||
if(code != close_code::none)
|
||||
{
|
||||
// _Fail the WebSocket Connection_
|
||||
return fail_op<Handler>{
|
||||
std::move(h_), ws_, code}();
|
||||
}
|
||||
return ws_.do_async_fail(
|
||||
code, error::failed, std::move(h_));
|
||||
step_ = do_loop + 1;
|
||||
return ws_.stream_.async_read_some(
|
||||
ws_.rd_.buf.prepare(read_size(
|
||||
@ -202,19 +200,17 @@ operator()(
|
||||
if(code != close_code::none)
|
||||
{
|
||||
// _Fail the WebSocket Connection_
|
||||
return fail_op<Handler>{
|
||||
std::move(h_), ws_, code}();
|
||||
return ws_.do_async_fail(
|
||||
code, error::failed, std::move(h_));
|
||||
}
|
||||
ws_.rd_.buf.consume(len);
|
||||
if(ws_.ctrl_cb_)
|
||||
ws_.ctrl_cb_(frame_type::close,
|
||||
ws_.cr_.reason);
|
||||
if(ws_.wr_close_)
|
||||
{
|
||||
// _Close the WebSocket Connection_
|
||||
return fail_op<Handler>{
|
||||
std::move(h_), ws_, fail_how::close}();
|
||||
}
|
||||
return ws_.do_async_fail(close_code::none,
|
||||
error::closed, std::move(h_));
|
||||
auto cr = ws_.cr_;
|
||||
if(cr.code == close_code::none)
|
||||
cr.code = close_code::normal;
|
||||
@ -224,8 +220,11 @@ operator()(
|
||||
flat_static_buffer_base>(
|
||||
ws_.rd_.fb, cr);
|
||||
// _Start the WebSocket Closing Handshake_
|
||||
return fail_op<Handler>{
|
||||
std::move(h_), ws_, fail_how::close}();
|
||||
return ws_.do_async_fail(
|
||||
cr.code == close_code::none ?
|
||||
close_code::normal :
|
||||
static_cast<close_code>(cr.code),
|
||||
error::closed, std::move(h_));
|
||||
}
|
||||
}
|
||||
if(ws_.rd_.fh.len == 0 && ! ws_.rd_.fh.fin)
|
||||
@ -485,11 +484,9 @@ operator()(
|
||||
if(! ws_.rd_.utf8.write(mb) ||
|
||||
(ws_.rd_.remain == 0 && ws_.rd_.fh.fin &&
|
||||
! ws_.rd_.utf8.finish()))
|
||||
{
|
||||
// _Fail the WebSocket Connection_
|
||||
return fail_op<Handler>{std::move(h_),
|
||||
ws_, close_code::bad_payload}({}, 0);
|
||||
}
|
||||
return ws_.do_async_fail(close_code::bad_payload,
|
||||
error::failed, std::move(h_));
|
||||
}
|
||||
bytes_written_ += bytes_transferred;
|
||||
ws_.rd_.size += bytes_transferred;
|
||||
@ -520,11 +517,9 @@ operator()(
|
||||
if(! ws_.rd_.utf8.write(mb) ||
|
||||
(ws_.rd_.remain == 0 && ws_.rd_.fh.fin &&
|
||||
! ws_.rd_.utf8.finish()))
|
||||
{
|
||||
// _Fail the WebSocket Connection_
|
||||
return fail_op<Handler>{std::move(h_),
|
||||
ws_, close_code::bad_payload}();
|
||||
}
|
||||
return ws_.do_async_fail(close_code::bad_payload,
|
||||
error::failed, std::move(h_));
|
||||
}
|
||||
bytes_written_ += bytes_transferred;
|
||||
ws_.rd_.size += bytes_transferred;
|
||||
@ -614,11 +609,9 @@ operator()(
|
||||
break;
|
||||
if(ws_.rd_msg_max_ && beast::detail::sum_exceeds(
|
||||
ws_.rd_.size, zs.total_out, ws_.rd_msg_max_))
|
||||
{
|
||||
// _Fail the WebSocket Connection_
|
||||
return fail_op<Handler>{std::move(h_),
|
||||
ws_, close_code::too_big}();
|
||||
}
|
||||
return ws_.do_async_fail(close_code::too_big,
|
||||
error::failed, std::move(h_));
|
||||
cb_.consume(zs.total_out);
|
||||
ws_.rd_.size += zs.total_out;
|
||||
ws_.rd_.remain -= zs.total_in;
|
||||
@ -632,11 +625,9 @@ operator()(
|
||||
buffer_prefix(bytes_written_, cb_.get())) || (
|
||||
ws_.rd_.remain == 0 && ws_.rd_.fh.fin &&
|
||||
! ws_.rd_.utf8.finish()))
|
||||
{
|
||||
// _Fail the WebSocket Connection_
|
||||
return fail_op<Handler>{std::move(h_),
|
||||
ws_, close_code::bad_payload}();
|
||||
}
|
||||
return ws_.do_async_fail(close_code::bad_payload,
|
||||
error::failed, std::move(h_));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -631,7 +631,7 @@ build_response(http::request<Body,
|
||||
template<class NextLayer>
|
||||
void
|
||||
stream<NextLayer>::
|
||||
do_response(response_type const& res,
|
||||
on_response(response_type const& res,
|
||||
detail::sec_ws_key_type const& key, error_code& ec)
|
||||
{
|
||||
bool const success = [&]()
|
||||
|
@ -3791,6 +3791,10 @@ private:
|
||||
http::basic_fields<Allocator>> const& req,
|
||||
Decorator const& decorator);
|
||||
|
||||
void
|
||||
on_response(response_type const& resp,
|
||||
detail::sec_ws_key_type const& key, error_code& ec);
|
||||
|
||||
template<class Decorator>
|
||||
void
|
||||
do_accept(Decorator const& decorator,
|
||||
@ -3811,8 +3815,17 @@ private:
|
||||
error_code& ec);
|
||||
|
||||
void
|
||||
do_response(response_type const& resp,
|
||||
detail::sec_ws_key_type const& key, error_code& ec);
|
||||
do_fail(
|
||||
close_code code,
|
||||
error_code ev,
|
||||
error_code& ec);
|
||||
|
||||
template<class Handler>
|
||||
void
|
||||
do_async_fail(
|
||||
close_code code,
|
||||
error_code ev,
|
||||
Handler&& handler);
|
||||
};
|
||||
|
||||
} // websocket
|
||||
|
Reference in New Issue
Block a user