mirror of
https://github.com/boostorg/beast.git
synced 2025-07-30 04:47:29 +02:00
websocket accept refactoring (API Change):
* stream overloads of accept which take both a message and a buffer sequence are removed. Actions Required: * Do not call websocket accept overloads which take both a message and a buffer sequence, as it is illegal per rfc6455.
This commit is contained in:
10
CHANGELOG.md
10
CHANGELOG.md
@ -4,6 +4,16 @@ WebSocket:
|
||||
|
||||
* Fix async_read_some handler signature
|
||||
|
||||
API Changes:
|
||||
|
||||
* websocket accept refactoring
|
||||
|
||||
Actions Required:
|
||||
|
||||
* Do not call websocket accept overloads which take
|
||||
both a message and a buffer sequence, as it is
|
||||
illegal per rfc6455.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Version 108:
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <boost/beast/core/buffer_prefix.hpp>
|
||||
#include <boost/beast/core/handler_ptr.hpp>
|
||||
#include <boost/beast/core/detail/type_traits.hpp>
|
||||
#include <boost/asio/coroutine.hpp>
|
||||
#include <boost/asio/handler_alloc_hook.hpp>
|
||||
#include <boost/asio/handler_continuation_hook.hpp>
|
||||
#include <boost/asio/handler_invoke_hook.hpp>
|
||||
@ -35,12 +36,12 @@ namespace websocket {
|
||||
template<class NextLayer>
|
||||
template<class Handler>
|
||||
class stream<NextLayer>::response_op
|
||||
: public boost::asio::coroutine
|
||||
{
|
||||
struct data
|
||||
{
|
||||
stream<NextLayer>& ws;
|
||||
response_type res;
|
||||
int step = 0;
|
||||
|
||||
template<class Body, class Allocator, class Decorator>
|
||||
data(Handler&, stream<NextLayer>& ws_, http::request<
|
||||
@ -66,10 +67,7 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
void operator()(Buffers const& buffers);
|
||||
|
||||
void operator()(error_code ec);
|
||||
void operator()(error_code ec = {});
|
||||
|
||||
friend
|
||||
void* asio_handler_allocate(
|
||||
@ -90,10 +88,11 @@ public:
|
||||
}
|
||||
|
||||
friend
|
||||
bool asio_handler_is_continuation(response_op*)
|
||||
bool asio_handler_is_continuation(response_op* op)
|
||||
{
|
||||
// VFALCO This will go away in Net-TS
|
||||
return false;
|
||||
using boost::asio::asio_handler_is_continuation;
|
||||
return asio_handler_is_continuation(
|
||||
std::addressof(op->d_.handler()));
|
||||
}
|
||||
|
||||
template<class Function>
|
||||
@ -106,37 +105,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template<class NextLayer>
|
||||
template<class Handler>
|
||||
template<class Buffers>
|
||||
void
|
||||
stream<NextLayer>::
|
||||
response_op<Handler>::
|
||||
operator()(Buffers const& buffers)
|
||||
{
|
||||
using boost::asio::buffer_copy;
|
||||
using boost::asio::buffer_size;
|
||||
auto& d = *d_;
|
||||
error_code ec;
|
||||
boost::optional<typename
|
||||
static_buffer_base::mutable_buffers_type> mb;
|
||||
auto const len = buffer_size(buffers);
|
||||
try
|
||||
{
|
||||
mb.emplace(d.ws.rd_.buf.prepare(len));
|
||||
}
|
||||
catch(std::length_error const&)
|
||||
{
|
||||
d.step = 2;
|
||||
ec = error::buffer_overflow;
|
||||
return d.ws.get_io_service().post(
|
||||
bind_handler(std::move(*this), ec));
|
||||
}
|
||||
d.ws.rd_.buf.commit(
|
||||
buffer_copy(*mb, buffers));
|
||||
(*this)(ec);
|
||||
}
|
||||
|
||||
template<class NextLayer>
|
||||
template<class Handler>
|
||||
void
|
||||
@ -145,18 +113,13 @@ response_op<Handler>::
|
||||
operator()(error_code ec)
|
||||
{
|
||||
auto& d = *d_;
|
||||
switch(d.step)
|
||||
BOOST_ASIO_CORO_REENTER(*this)
|
||||
{
|
||||
case 0:
|
||||
// send response
|
||||
d.step = 1;
|
||||
// Send response
|
||||
BOOST_ASIO_CORO_YIELD
|
||||
http::async_write(d.ws.next_layer(),
|
||||
d.res, std::move(*this));
|
||||
return;
|
||||
|
||||
// sent response
|
||||
case 1:
|
||||
if(d.res.result() !=
|
||||
if(! ec && d.res.result() !=
|
||||
http::status::switching_protocols)
|
||||
ec = error::handshake_failed;
|
||||
if(! ec)
|
||||
@ -164,13 +127,8 @@ operator()(error_code ec)
|
||||
pmd_read(d.ws.pmd_config_, d.res);
|
||||
d.ws.open(role_type::server);
|
||||
}
|
||||
break;
|
||||
|
||||
// call handler
|
||||
case 2:
|
||||
break;
|
||||
d_.invoke(ec);
|
||||
}
|
||||
d_.invoke(ec);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@ -180,13 +138,13 @@ operator()(error_code ec)
|
||||
template<class NextLayer>
|
||||
template<class Decorator, class Handler>
|
||||
class stream<NextLayer>::accept_op
|
||||
: public boost::asio::coroutine
|
||||
{
|
||||
struct data
|
||||
{
|
||||
stream<NextLayer>& ws;
|
||||
Decorator decorator;
|
||||
http::request_parser<http::empty_body> p;
|
||||
int step = 0;
|
||||
data(Handler&, stream<NextLayer>& ws_,
|
||||
Decorator const& decorator_)
|
||||
: ws(ws_)
|
||||
@ -210,9 +168,9 @@ public:
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
void operator()(Buffers const& buffers);
|
||||
void run(Buffers const& buffers);
|
||||
|
||||
void operator()(error_code ec);
|
||||
void operator()(error_code ec = {});
|
||||
|
||||
friend
|
||||
void* asio_handler_allocate(
|
||||
@ -256,7 +214,7 @@ template<class Buffers>
|
||||
void
|
||||
stream<NextLayer>::
|
||||
accept_op<Decorator, Handler>::
|
||||
operator()(Buffers const& buffers)
|
||||
run(Buffers const& buffers)
|
||||
{
|
||||
using boost::asio::buffer_copy;
|
||||
using boost::asio::buffer_size;
|
||||
@ -271,10 +229,8 @@ operator()(Buffers const& buffers)
|
||||
}
|
||||
catch(std::length_error const&)
|
||||
{
|
||||
d.step = 2;
|
||||
ec = error::buffer_overflow;
|
||||
return d.ws.get_io_service().post(
|
||||
bind_handler(std::move(*this), ec));
|
||||
return (*this)(ec);
|
||||
}
|
||||
d.ws.rd_.buf.commit(
|
||||
buffer_copy(*mb, buffers));
|
||||
@ -289,40 +245,45 @@ accept_op<Decorator, Handler>::
|
||||
operator()(error_code ec)
|
||||
{
|
||||
auto& d = *d_;
|
||||
switch(d.step)
|
||||
BOOST_ASIO_CORO_REENTER(*this)
|
||||
{
|
||||
case 0:
|
||||
d.step = 1;
|
||||
return http::async_read(
|
||||
d.ws.next_layer(), d.ws.rd_.buf,
|
||||
d.p, std::move(*this));
|
||||
|
||||
case 1:
|
||||
{
|
||||
if(ec == http::error::end_of_stream)
|
||||
ec = error::closed;
|
||||
if(ec)
|
||||
break;
|
||||
// Arguments from our step must be
|
||||
// moved to the stack before releasing
|
||||
// the handler.
|
||||
auto& ws = d.ws;
|
||||
auto const req = d.p.release();
|
||||
auto const decorator = d.decorator;
|
||||
#if 1
|
||||
return response_op<Handler>{
|
||||
d_.release_handler(),
|
||||
ws, req, decorator}(ec);
|
||||
#else
|
||||
// VFALCO This *should* work but breaks
|
||||
// coroutine invariants in the unit test.
|
||||
// Also it calls reset() when it shouldn't.
|
||||
return ws.async_accept_ex(
|
||||
req, decorator, d_.release_handler());
|
||||
#endif
|
||||
{
|
||||
BOOST_ASIO_CORO_YIELD
|
||||
d.ws.get_io_service().post(
|
||||
bind_handler(std::move(*this), ec));
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_ASIO_CORO_YIELD
|
||||
http::async_read(
|
||||
d.ws.next_layer(), d.ws.rd_.buf,
|
||||
d.p, std::move(*this));
|
||||
if(ec == http::error::end_of_stream)
|
||||
ec = error::closed;
|
||||
if(! ec)
|
||||
{
|
||||
// Arguments from our step must be
|
||||
// moved to the stack before releasing
|
||||
// the handler.
|
||||
auto& ws = d.ws;
|
||||
auto const req = d.p.release();
|
||||
auto const decorator = d.decorator;
|
||||
#if 1
|
||||
return response_op<Handler>{
|
||||
d_.release_handler(),
|
||||
ws, req, decorator}(ec);
|
||||
#else
|
||||
// VFALCO This *should* work but breaks
|
||||
// coroutine invariants in the unit test.
|
||||
// Also it calls reset() when it shouldn't.
|
||||
return ws.async_accept_ex(
|
||||
req, decorator, d_.release_handler());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
d_.invoke(ec);
|
||||
}
|
||||
}
|
||||
d_.invoke(ec);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@ -403,11 +364,13 @@ accept(ConstBufferSequence const& buffers)
|
||||
|
||||
template<class NextLayer>
|
||||
template<
|
||||
class ConstBufferSequence, class ResponseDecorator>
|
||||
class ConstBufferSequence,
|
||||
class ResponseDecorator>
|
||||
typename std::enable_if<! http::detail::is_header<
|
||||
ConstBufferSequence>::value>::type
|
||||
stream<NextLayer>::
|
||||
accept_ex(ConstBufferSequence const& buffers,
|
||||
accept_ex(
|
||||
ConstBufferSequence const& buffers,
|
||||
ResponseDecorator const &decorator)
|
||||
{
|
||||
static_assert(is_sync_stream<next_layer_type>::value,
|
||||
@ -429,30 +392,45 @@ template<class ConstBufferSequence>
|
||||
typename std::enable_if<! http::detail::is_header<
|
||||
ConstBufferSequence>::value>::type
|
||||
stream<NextLayer>::
|
||||
accept(ConstBufferSequence const& buffers, error_code& ec)
|
||||
accept(
|
||||
ConstBufferSequence const& buffers, error_code& ec)
|
||||
{
|
||||
static_assert(is_sync_stream<next_layer_type>::value,
|
||||
"SyncStream requirements not met");
|
||||
static_assert(is_const_buffer_sequence<
|
||||
ConstBufferSequence>::value,
|
||||
"ConstBufferSequence requirements not met");
|
||||
reset();
|
||||
using boost::asio::buffer_copy;
|
||||
using boost::asio::buffer_size;
|
||||
rd_.buf.commit(buffer_copy(
|
||||
rd_.buf.prepare(
|
||||
buffer_size(buffers)), buffers));
|
||||
reset();
|
||||
boost::optional<typename
|
||||
static_buffer_base::mutable_buffers_type> mb;
|
||||
try
|
||||
{
|
||||
mb.emplace(rd_.buf.prepare(
|
||||
buffer_size(buffers)));
|
||||
}
|
||||
catch(std::length_error const&)
|
||||
{
|
||||
ec = error::buffer_overflow;
|
||||
return;
|
||||
}
|
||||
rd_.buf.commit(
|
||||
buffer_copy(*mb, buffers));
|
||||
do_accept(&default_decorate_res, ec);
|
||||
}
|
||||
|
||||
template<class NextLayer>
|
||||
template<
|
||||
class ConstBufferSequence, class ResponseDecorator>
|
||||
class ConstBufferSequence,
|
||||
class ResponseDecorator>
|
||||
typename std::enable_if<! http::detail::is_header<
|
||||
ConstBufferSequence>::value>::type
|
||||
stream<NextLayer>::
|
||||
accept_ex(ConstBufferSequence const& buffers,
|
||||
ResponseDecorator const& decorator, error_code& ec)
|
||||
accept_ex(
|
||||
ConstBufferSequence const& buffers,
|
||||
ResponseDecorator const& decorator,
|
||||
error_code& ec)
|
||||
{
|
||||
static_assert(is_sync_stream<next_layer_type>::value,
|
||||
"SyncStream requirements not met");
|
||||
@ -462,12 +440,22 @@ accept_ex(ConstBufferSequence const& buffers,
|
||||
static_assert(is_const_buffer_sequence<
|
||||
ConstBufferSequence>::value,
|
||||
"ConstBufferSequence requirements not met");
|
||||
reset();
|
||||
using boost::asio::buffer_copy;
|
||||
using boost::asio::buffer_size;
|
||||
rd_.buf.commit(buffer_copy(
|
||||
rd_.buf.prepare(
|
||||
buffer_size(buffers)), buffers));
|
||||
reset();
|
||||
boost::optional<typename
|
||||
static_buffer_base::mutable_buffers_type> mb;
|
||||
try
|
||||
{
|
||||
mb.emplace(rd_.buf.prepare(
|
||||
buffer_size(buffers)));
|
||||
}
|
||||
catch(std::length_error const&)
|
||||
{
|
||||
ec = error::buffer_overflow;
|
||||
return;
|
||||
}
|
||||
rd_.buf.commit(buffer_copy(*mb, buffers));
|
||||
do_accept(decorator, ec);
|
||||
}
|
||||
|
||||
@ -475,8 +463,9 @@ template<class NextLayer>
|
||||
template<class Body, class Allocator>
|
||||
void
|
||||
stream<NextLayer>::
|
||||
accept(http::request<Body,
|
||||
http::basic_fields<Allocator>> const& req)
|
||||
accept(
|
||||
http::request<Body,
|
||||
http::basic_fields<Allocator>> const& req)
|
||||
{
|
||||
static_assert(is_sync_stream<next_layer_type>::value,
|
||||
"SyncStream requirements not met");
|
||||
@ -487,12 +476,14 @@ accept(http::request<Body,
|
||||
}
|
||||
|
||||
template<class NextLayer>
|
||||
template<class Body,
|
||||
class Allocator, class ResponseDecorator>
|
||||
template<
|
||||
class Body, class Allocator,
|
||||
class ResponseDecorator>
|
||||
void
|
||||
stream<NextLayer>::
|
||||
accept_ex(http::request<Body,
|
||||
http::basic_fields<Allocator>> const& req,
|
||||
accept_ex(
|
||||
http::request<Body,
|
||||
http::basic_fields<Allocator>> const& req,
|
||||
ResponseDecorator const& decorator)
|
||||
{
|
||||
static_assert(is_sync_stream<next_layer_type>::value,
|
||||
@ -510,9 +501,10 @@ template<class NextLayer>
|
||||
template<class Body, class Allocator>
|
||||
void
|
||||
stream<NextLayer>::
|
||||
accept(http::request<Body,
|
||||
http::basic_fields<Allocator>> const& req,
|
||||
error_code& ec)
|
||||
accept(
|
||||
http::request<Body,
|
||||
http::basic_fields<Allocator>> const& req,
|
||||
error_code& ec)
|
||||
{
|
||||
static_assert(is_sync_stream<next_layer_type>::value,
|
||||
"SyncStream requirements not met");
|
||||
@ -521,13 +513,16 @@ accept(http::request<Body,
|
||||
}
|
||||
|
||||
template<class NextLayer>
|
||||
template<class Body, class Allocator,
|
||||
template<
|
||||
class Body, class Allocator,
|
||||
class ResponseDecorator>
|
||||
void
|
||||
stream<NextLayer>::
|
||||
accept_ex(http::request<Body,
|
||||
http::basic_fields<Allocator>> const& req,
|
||||
ResponseDecorator const& decorator, error_code& ec)
|
||||
accept_ex(
|
||||
http::request<Body,
|
||||
http::basic_fields<Allocator>> const& req,
|
||||
ResponseDecorator const& decorator,
|
||||
error_code& ec)
|
||||
{
|
||||
static_assert(is_sync_stream<next_layer_type>::value,
|
||||
"SyncStream requirements not met");
|
||||
@ -538,101 +533,6 @@ accept_ex(http::request<Body,
|
||||
do_accept(req, decorator, ec);
|
||||
}
|
||||
|
||||
template<class NextLayer>
|
||||
template<class Body, class Allocator,
|
||||
class ConstBufferSequence>
|
||||
void
|
||||
stream<NextLayer>::
|
||||
accept(http::request<Body,
|
||||
http::basic_fields<Allocator>> const& req,
|
||||
ConstBufferSequence const& buffers)
|
||||
{
|
||||
static_assert(is_sync_stream<next_layer_type>::value,
|
||||
"SyncStream requirements not met");
|
||||
static_assert(is_const_buffer_sequence<
|
||||
ConstBufferSequence>::value,
|
||||
"ConstBufferSequence requirements not met");
|
||||
error_code ec;
|
||||
accept(req, buffers, ec);
|
||||
if(ec)
|
||||
BOOST_THROW_EXCEPTION(system_error{ec});
|
||||
}
|
||||
|
||||
template<class NextLayer>
|
||||
template<class Body, class Allocator,
|
||||
class ConstBufferSequence, class ResponseDecorator>
|
||||
void
|
||||
stream<NextLayer>::
|
||||
accept_ex(http::request<Body,
|
||||
http::basic_fields<Allocator>> const& req,
|
||||
ConstBufferSequence const& buffers,
|
||||
ResponseDecorator const& decorator)
|
||||
{
|
||||
static_assert(is_sync_stream<next_layer_type>::value,
|
||||
"SyncStream requirements not met");
|
||||
static_assert(is_const_buffer_sequence<
|
||||
ConstBufferSequence>::value,
|
||||
"ConstBufferSequence requirements not met");
|
||||
static_assert(detail::is_ResponseDecorator<
|
||||
ResponseDecorator>::value,
|
||||
"ResponseDecorator requirements not met");
|
||||
error_code ec;
|
||||
accept_ex(req, buffers, decorator, ec);
|
||||
if(ec)
|
||||
BOOST_THROW_EXCEPTION(system_error{ec});
|
||||
}
|
||||
|
||||
template<class NextLayer>
|
||||
template<class Body, class Allocator,
|
||||
class ConstBufferSequence>
|
||||
void
|
||||
stream<NextLayer>::
|
||||
accept(http::request<Body,
|
||||
http::basic_fields<Allocator>> const& req,
|
||||
ConstBufferSequence const& buffers, error_code& ec)
|
||||
{
|
||||
static_assert(is_sync_stream<next_layer_type>::value,
|
||||
"SyncStream requirements not met");
|
||||
static_assert(is_const_buffer_sequence<
|
||||
ConstBufferSequence>::value,
|
||||
"ConstBufferSequence requirements not met");
|
||||
reset();
|
||||
using boost::asio::buffer_copy;
|
||||
using boost::asio::buffer_size;
|
||||
rd_.buf.commit(buffer_copy(
|
||||
rd_.buf.prepare(
|
||||
buffer_size(buffers)), buffers));
|
||||
do_accept(req, &default_decorate_res, ec);
|
||||
}
|
||||
|
||||
template<class NextLayer>
|
||||
template<class Body, class Allocator,
|
||||
class ConstBufferSequence, class ResponseDecorator>
|
||||
void
|
||||
stream<NextLayer>::
|
||||
accept_ex(http::request<Body,
|
||||
http::basic_fields<Allocator>> const& req,
|
||||
ConstBufferSequence const& buffers,
|
||||
ResponseDecorator const& decorator,
|
||||
error_code& ec)
|
||||
{
|
||||
static_assert(is_sync_stream<next_layer_type>::value,
|
||||
"SyncStream requirements not met");
|
||||
static_assert(is_const_buffer_sequence<
|
||||
ConstBufferSequence>::value,
|
||||
"ConstBufferSequence requirements not met");
|
||||
static_assert(detail::is_ResponseDecorator<
|
||||
ResponseDecorator>::value,
|
||||
"ResponseDecorator requirements not met");
|
||||
reset();
|
||||
using boost::asio::buffer_copy;
|
||||
using boost::asio::buffer_size;
|
||||
rd_.buf.commit(buffer_copy(
|
||||
rd_.buf.prepare(
|
||||
buffer_size(buffers)), buffers));
|
||||
do_accept(req, decorator, ec);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<class NextLayer>
|
||||
@ -709,7 +609,7 @@ async_accept(
|
||||
handler_type<AcceptHandler, void(error_code)>>{
|
||||
init.completion_handler,
|
||||
*this,
|
||||
&default_decorate_res}(buffers);
|
||||
&default_decorate_res}.run(buffers);
|
||||
return init.result.get();
|
||||
}
|
||||
|
||||
@ -743,7 +643,7 @@ async_accept_ex(
|
||||
handler_type<AcceptHandler, void(error_code)>>{
|
||||
init.completion_handler,
|
||||
*this,
|
||||
decorator}(buffers);
|
||||
decorator}.run(buffers);
|
||||
return init.result.get();
|
||||
}
|
||||
|
||||
@ -768,7 +668,7 @@ async_accept(
|
||||
init.completion_handler,
|
||||
*this,
|
||||
req,
|
||||
&default_decorate_res}({});
|
||||
&default_decorate_res}();
|
||||
return init.result.get();
|
||||
}
|
||||
|
||||
@ -798,73 +698,7 @@ async_accept_ex(
|
||||
init.completion_handler,
|
||||
*this,
|
||||
req,
|
||||
decorator}({});
|
||||
return init.result.get();
|
||||
}
|
||||
|
||||
template<class NextLayer>
|
||||
template<
|
||||
class Body, class Allocator,
|
||||
class ConstBufferSequence,
|
||||
class AcceptHandler>
|
||||
async_return_type<AcceptHandler, void(error_code)>
|
||||
stream<NextLayer>::
|
||||
async_accept(
|
||||
http::request<Body, http::basic_fields<Allocator>> const& req,
|
||||
ConstBufferSequence const& buffers,
|
||||
AcceptHandler&& handler)
|
||||
{
|
||||
static_assert(is_async_stream<next_layer_type>::value,
|
||||
"AsyncStream requirements requirements not met");
|
||||
static_assert(is_const_buffer_sequence<
|
||||
ConstBufferSequence>::value,
|
||||
"ConstBufferSequence requirements not met");
|
||||
async_completion<AcceptHandler,
|
||||
void(error_code)> init{handler};
|
||||
reset();
|
||||
using boost::asio::asio_handler_is_continuation;
|
||||
response_op<
|
||||
handler_type<AcceptHandler, void(error_code)>>{
|
||||
init.completion_handler,
|
||||
*this,
|
||||
req,
|
||||
&default_decorate_res}(buffers);
|
||||
return init.result.get();
|
||||
}
|
||||
|
||||
template<class NextLayer>
|
||||
template<
|
||||
class Body, class Allocator,
|
||||
class ConstBufferSequence,
|
||||
class ResponseDecorator,
|
||||
class AcceptHandler>
|
||||
async_return_type<
|
||||
AcceptHandler, void(error_code)>
|
||||
stream<NextLayer>::
|
||||
async_accept_ex(http::request<Body,
|
||||
http::basic_fields<Allocator>> const& req,
|
||||
ConstBufferSequence const& buffers,
|
||||
ResponseDecorator const& decorator,
|
||||
AcceptHandler&& handler)
|
||||
{
|
||||
static_assert(is_async_stream<next_layer_type>::value,
|
||||
"AsyncStream requirements requirements not met");
|
||||
static_assert(is_const_buffer_sequence<
|
||||
ConstBufferSequence>::value,
|
||||
"ConstBufferSequence requirements not met");
|
||||
static_assert(detail::is_ResponseDecorator<
|
||||
ResponseDecorator>::value,
|
||||
"ResponseDecorator requirements not met");
|
||||
async_completion<AcceptHandler,
|
||||
void(error_code)> init{handler};
|
||||
reset();
|
||||
using boost::asio::asio_handler_is_continuation;
|
||||
response_op<
|
||||
handler_type<AcceptHandler, void(error_code)>>{
|
||||
init.completion_handler,
|
||||
*this,
|
||||
req,
|
||||
decorator}(buffers);
|
||||
decorator}();
|
||||
return init.result.get();
|
||||
}
|
||||
|
||||
|
@ -1915,212 +1915,6 @@ public:
|
||||
ResponseDecorator const& decorator,
|
||||
error_code& ec);
|
||||
|
||||
/** Respond to a WebSocket HTTP Upgrade request
|
||||
|
||||
This function is used to synchronously send the HTTP response
|
||||
to an HTTP request possibly containing a WebSocket Upgrade.
|
||||
The call blocks until one of the following conditions is true:
|
||||
|
||||
@li The response finishes sending.
|
||||
|
||||
@li An error occurs on the stream.
|
||||
|
||||
This function is implemented in terms of one or more calls to
|
||||
the next layer's `read_some` and `write_some` functions.
|
||||
|
||||
If the stream receives a valid HTTP WebSocket Upgrade request,
|
||||
an HTTP response is sent back indicating a successful upgrade.
|
||||
When this call returns, the stream is then ready to send and
|
||||
receive WebSocket protocol frames and messages.
|
||||
If the HTTP Upgrade request is invalid or cannot be satisfied,
|
||||
an HTTP response is sent indicating the reason and status code
|
||||
(typically 400, "Bad Request"). This counts as a failure.
|
||||
|
||||
The implementation uses fixed size internal storage to
|
||||
copy the buffer. If the buffer is too large, the error
|
||||
@ref error::buffer_overflow will be indicated. Applications
|
||||
that wish to supply larger buffers should wrap the next layer
|
||||
in a @ref buffered_read_stream and store the buffer contents in
|
||||
the wrapper before calling accept.
|
||||
|
||||
@param req An object containing the HTTP Upgrade request.
|
||||
Ownership is not transferred, the implementation will not
|
||||
access this object from other threads.
|
||||
|
||||
@param buffers Caller provided data that has already been
|
||||
received on the stream. This must not include the octets
|
||||
corresponding to the HTTP Upgrade request. The implementation
|
||||
will copy the caller provided data before the function returns.
|
||||
|
||||
@throws system_error Thrown on failure.
|
||||
*/
|
||||
template<class Body, class Allocator,
|
||||
class ConstBufferSequence>
|
||||
void
|
||||
accept(http::request<Body,
|
||||
http::basic_fields<Allocator>> const& req,
|
||||
ConstBufferSequence const& buffers);
|
||||
|
||||
/** Respond to a WebSocket HTTP Upgrade request
|
||||
|
||||
This function is used to synchronously send the HTTP response
|
||||
to an HTTP request possibly containing a WebSocket Upgrade.
|
||||
The call blocks until one of the following conditions is true:
|
||||
|
||||
@li The response finishes sending.
|
||||
|
||||
@li An error occurs on the stream.
|
||||
|
||||
This function is implemented in terms of one or more calls to
|
||||
the next layer's `read_some` and `write_some` functions.
|
||||
|
||||
If the stream receives a valid HTTP WebSocket Upgrade request,
|
||||
an HTTP response is sent back indicating a successful upgrade.
|
||||
When this call returns, the stream is then ready to send and
|
||||
receive WebSocket protocol frames and messages.
|
||||
If the HTTP Upgrade request is invalid or cannot be satisfied,
|
||||
an HTTP response is sent indicating the reason and status code
|
||||
(typically 400, "Bad Request"). This counts as a failure.
|
||||
|
||||
The implementation uses fixed size internal storage to
|
||||
copy the buffer. If the buffer is too large, the error
|
||||
@ref error::buffer_overflow will be indicated. Applications
|
||||
that wish to supply larger buffers should wrap the next layer
|
||||
in a @ref buffered_read_stream and store the buffer contents in
|
||||
the wrapper before calling accept.
|
||||
|
||||
@param req An object containing the HTTP Upgrade request.
|
||||
Ownership is not transferred, the implementation will not
|
||||
access this object from other threads.
|
||||
|
||||
@param buffers Caller provided data that has already been
|
||||
received on the stream. This must not include the octets
|
||||
corresponding to the HTTP Upgrade request. The implementation
|
||||
will copy the caller provided data before the function returns.
|
||||
|
||||
@param decorator A function object which will be called to modify
|
||||
the HTTP response object delivered by the implementation. This
|
||||
could be used to set the Server field, subprotocols, or other
|
||||
application or HTTP specific fields. The object will be called
|
||||
with this equivalent signature:
|
||||
@code void decorator(
|
||||
response_type& res
|
||||
); @endcode
|
||||
|
||||
@throws system_error Thrown on failure.
|
||||
*/
|
||||
template<class Body, class Allocator,
|
||||
class ConstBufferSequence, class ResponseDecorator>
|
||||
void
|
||||
accept_ex(http::request<Body,
|
||||
http::basic_fields<Allocator>> const& req,
|
||||
ConstBufferSequence const& buffers,
|
||||
ResponseDecorator const& decorator);
|
||||
|
||||
/** Respond to a WebSocket HTTP Upgrade request
|
||||
|
||||
This function is used to synchronously send the HTTP response
|
||||
to an HTTP request possibly containing a WebSocket Upgrade.
|
||||
The call blocks until one of the following conditions is true:
|
||||
|
||||
@li The response finishes sending.
|
||||
|
||||
@li An error occurs on the stream.
|
||||
|
||||
This function is implemented in terms of one or more calls to
|
||||
the next layer's `read_some` and `write_some` functions.
|
||||
|
||||
If the stream receives a valid HTTP WebSocket Upgrade request,
|
||||
an HTTP response is sent back indicating a successful upgrade.
|
||||
When this call returns, the stream is then ready to send and
|
||||
receive WebSocket protocol frames and messages.
|
||||
If the HTTP Upgrade request is invalid or cannot be satisfied,
|
||||
an HTTP response is sent indicating the reason and status code
|
||||
(typically 400, "Bad Request"). This counts as a failure.
|
||||
|
||||
The implementation uses fixed size internal storage to
|
||||
copy the buffer. If the buffer is too large, the error
|
||||
@ref error::buffer_overflow will be indicated. Applications
|
||||
that wish to supply larger buffers should wrap the next layer
|
||||
in a @ref buffered_read_stream and store the buffer contents in
|
||||
the wrapper before calling accept.
|
||||
|
||||
@param req An object containing the HTTP Upgrade request.
|
||||
Ownership is not transferred, the implementation will not
|
||||
access this object from other threads.
|
||||
|
||||
@param buffers Caller provided data that has already been
|
||||
received on the stream. This must not include the octets
|
||||
corresponding to the HTTP Upgrade request. The implementation
|
||||
will copy the caller provided data before the function returns.
|
||||
|
||||
@param ec Set to indicate what error occurred, if any.
|
||||
*/
|
||||
template<class Body, class Allocator,
|
||||
class ConstBufferSequence>
|
||||
void
|
||||
accept(http::request<Body,
|
||||
http::basic_fields<Allocator>> const& req,
|
||||
ConstBufferSequence const& buffers,
|
||||
error_code& ec);
|
||||
|
||||
/** Respond to a WebSocket HTTP Upgrade request
|
||||
|
||||
This function is used to synchronously send the HTTP response
|
||||
to an HTTP request possibly containing a WebSocket Upgrade.
|
||||
The call blocks until one of the following conditions is true:
|
||||
|
||||
@li The response finishes sending.
|
||||
|
||||
@li An error occurs on the stream.
|
||||
|
||||
This function is implemented in terms of one or more calls to
|
||||
the next layer's `read_some` and `write_some` functions.
|
||||
|
||||
If the stream receives a valid HTTP WebSocket Upgrade request,
|
||||
an HTTP response is sent back indicating a successful upgrade.
|
||||
When this call returns, the stream is then ready to send and
|
||||
receive WebSocket protocol frames and messages.
|
||||
If the HTTP Upgrade request is invalid or cannot be satisfied,
|
||||
an HTTP response is sent indicating the reason and status code
|
||||
(typically 400, "Bad Request"). This counts as a failure.
|
||||
|
||||
The implementation uses fixed size internal storage to
|
||||
copy the buffer. If the buffer is too large, the error
|
||||
@ref error::buffer_overflow will be indicated. Applications
|
||||
that wish to supply larger buffers should wrap the next layer
|
||||
in a @ref buffered_read_stream and store the buffer contents in
|
||||
the wrapper before calling accept.
|
||||
|
||||
@param req An object containing the HTTP Upgrade request.
|
||||
Ownership is not transferred, the implementation will not
|
||||
access this object from other threads.
|
||||
|
||||
@param buffers Caller provided data that has already been
|
||||
received on the stream. This must not include the octets
|
||||
corresponding to the HTTP Upgrade request. The implementation
|
||||
will copy the caller provided data before the function returns.
|
||||
|
||||
@param decorator A function object which will be called to modify
|
||||
the HTTP response object delivered by the implementation. This
|
||||
could be used to set the Server field, subprotocols, or other
|
||||
application or HTTP specific fields. The object will be called
|
||||
with this equivalent signature:
|
||||
@code void decorator(
|
||||
response_type& res
|
||||
); @endcode
|
||||
|
||||
@param ec Set to indicate what error occurred, if any.
|
||||
*/
|
||||
template<class Body, class Allocator,
|
||||
class ConstBufferSequence, class ResponseDecorator>
|
||||
void
|
||||
accept_ex(http::request<Body,
|
||||
http::basic_fields<Allocator>> const& req,
|
||||
ConstBufferSequence const& buffers,
|
||||
ResponseDecorator const& decorator,
|
||||
error_code& ec);
|
||||
|
||||
/** Start reading and responding to a WebSocket HTTP Upgrade request.
|
||||
|
||||
This function is used to asynchronously read an HTTP WebSocket
|
||||
@ -2233,202 +2027,8 @@ public:
|
||||
this function. Invocation of the handler will be performed in a
|
||||
manner equivalent to using `boost::asio::io_service::post`.
|
||||
*/
|
||||
template<class ResponseDecorator, class AcceptHandler>
|
||||
#if BOOST_BEAST_DOXYGEN
|
||||
void_or_deduced
|
||||
#else
|
||||
async_return_type<
|
||||
AcceptHandler, void(error_code)>
|
||||
#endif
|
||||
async_accept_ex(ResponseDecorator const& decorator,
|
||||
AcceptHandler&& handler);
|
||||
|
||||
/** Start reading and responding to a WebSocket HTTP Upgrade request.
|
||||
|
||||
This function is used to asynchronously read an HTTP WebSocket
|
||||
Upgrade request and send the HTTP response. The function call
|
||||
always returns immediately. The asynchronous operation will
|
||||
continue until one of the following conditions is true:
|
||||
|
||||
@li The request is received and the response finishes sending.
|
||||
|
||||
@li An error occurs on the stream.
|
||||
|
||||
This operation is implemented in terms of one or more calls to
|
||||
the next layer's `async_read_some` and `async_write_some`
|
||||
functions, and is known as a <em>composed operation</em>. The
|
||||
program must ensure that the stream performs no other
|
||||
asynchronous operations until this operation completes.
|
||||
|
||||
If the stream receives a valid HTTP WebSocket Upgrade request,
|
||||
an HTTP response is sent back indicating a successful upgrade.
|
||||
When the completion handler is invoked, the stream is then
|
||||
ready to send and receive WebSocket protocol frames and
|
||||
messages.
|
||||
If the HTTP Upgrade request is invalid or cannot be satisfied,
|
||||
an HTTP response is sent indicating the reason and status code
|
||||
(typically 400, "Bad Request"). This counts as a failure, and
|
||||
the completion handler will be invoked with a suitable error
|
||||
code set.
|
||||
|
||||
The implementation uses fixed size internal storage to
|
||||
receive the request. If the request is too large, the error
|
||||
@ref error::buffer_overflow will be indicated. Applications
|
||||
that wish to receive larger requests should first read the
|
||||
request using their own buffer and a suitable overload of
|
||||
@ref http::read or @ref http::async_read, then call @ref accept
|
||||
or @ref async_accept with the request.
|
||||
|
||||
@param buffers Caller provided data that has already been
|
||||
received on the stream. This may be used for implementations
|
||||
allowing multiple protocols on the same stream. The
|
||||
buffered data will first be applied to the handshake, and
|
||||
then to received WebSocket frames. The implementation will
|
||||
copy the caller provided data before the function returns.
|
||||
|
||||
@param handler The handler to be called when the request
|
||||
completes. Copies will be made of the handler as required. The
|
||||
equivalent function signature of the handler must be:
|
||||
@code void handler(
|
||||
error_code const& 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 `boost::asio::io_service::post`.
|
||||
*/
|
||||
template<class ConstBufferSequence, class AcceptHandler>
|
||||
#if BOOST_BEAST_DOXYGEN
|
||||
void_or_deduced
|
||||
#else
|
||||
typename std::enable_if<
|
||||
! http::detail::is_header<ConstBufferSequence>::value,
|
||||
async_return_type<AcceptHandler, void(error_code)>>::type
|
||||
#endif
|
||||
async_accept(ConstBufferSequence const& buffers,
|
||||
AcceptHandler&& handler);
|
||||
|
||||
/** Start reading and responding to a WebSocket HTTP Upgrade request.
|
||||
|
||||
This function is used to asynchronously read an HTTP WebSocket
|
||||
Upgrade request and send the HTTP response. The function call
|
||||
always returns immediately. The asynchronous operation will
|
||||
continue until one of the following conditions is true:
|
||||
|
||||
@li The request is received and the response finishes sending.
|
||||
|
||||
@li An error occurs on the stream.
|
||||
|
||||
This operation is implemented in terms of one or more calls to
|
||||
the next layer's `async_read_some` and `async_write_some`
|
||||
functions, and is known as a <em>composed operation</em>. The
|
||||
program must ensure that the stream performs no other
|
||||
asynchronous operations until this operation completes.
|
||||
|
||||
If the stream receives a valid HTTP WebSocket Upgrade request,
|
||||
an HTTP response is sent back indicating a successful upgrade.
|
||||
When the completion handler is invoked, the stream is then
|
||||
ready to send and receive WebSocket protocol frames and
|
||||
messages.
|
||||
If the HTTP Upgrade request is invalid or cannot be satisfied,
|
||||
an HTTP response is sent indicating the reason and status code
|
||||
(typically 400, "Bad Request"). This counts as a failure, and
|
||||
the completion handler will be invoked with a suitable error
|
||||
code set.
|
||||
|
||||
The implementation uses fixed size internal storage to
|
||||
receive the request. If the request is too large, the error
|
||||
@ref error::buffer_overflow will be indicated. Applications
|
||||
that wish to receive larger requests should first read the
|
||||
request using their own buffer and a suitable overload of
|
||||
@ref http::read or @ref http::async_read, then call @ref accept
|
||||
or @ref async_accept with the request.
|
||||
|
||||
@param buffers Caller provided data that has already been
|
||||
received on the stream. This may be used for implementations
|
||||
allowing multiple protocols on the same stream. The
|
||||
buffered data will first be applied to the handshake, and
|
||||
then to received WebSocket frames. The implementation will
|
||||
copy the caller provided data before the function returns.
|
||||
|
||||
@param decorator A function object which will be called to modify
|
||||
the HTTP response object delivered by the implementation. This
|
||||
could be used to set the Server field, subprotocols, or other
|
||||
application or HTTP specific fields. The object will be called
|
||||
with this equivalent signature:
|
||||
@code void decorator(
|
||||
response_type& res
|
||||
); @endcode
|
||||
|
||||
@param handler The handler to be called when the request
|
||||
completes. Copies will be made of the handler as required. The
|
||||
equivalent function signature of the handler must be:
|
||||
@code void handler(
|
||||
error_code const& 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 `boost::asio::io_service::post`.
|
||||
*/
|
||||
template<class ConstBufferSequence,
|
||||
class ResponseDecorator, class AcceptHandler>
|
||||
#if BOOST_BEAST_DOXYGEN
|
||||
void_or_deduced
|
||||
#else
|
||||
typename std::enable_if<
|
||||
! http::detail::is_header<ConstBufferSequence>::value,
|
||||
async_return_type<AcceptHandler, void(error_code)>>::type
|
||||
#endif
|
||||
async_accept_ex(ConstBufferSequence const& buffers,
|
||||
ResponseDecorator const& decorator,
|
||||
AcceptHandler&& handler);
|
||||
|
||||
/** Start responding to a WebSocket HTTP Upgrade request.
|
||||
|
||||
This function is used to asynchronously send the HTTP response
|
||||
to an HTTP request possibly containing a WebSocket Upgrade
|
||||
request. The function call always returns immediately. The
|
||||
asynchronous operation will continue until one of the following
|
||||
conditions is true:
|
||||
|
||||
@li The response finishes sending.
|
||||
|
||||
@li An error occurs on the stream.
|
||||
|
||||
This operation is implemented in terms of one or more calls to
|
||||
the next layer's `async_write_some` functions, and is known as
|
||||
a <em>composed operation</em>. The program must ensure that the
|
||||
stream performs no other operations until this operation
|
||||
completes.
|
||||
|
||||
If the stream receives a valid HTTP WebSocket Upgrade request,
|
||||
an HTTP response is sent back indicating a successful upgrade.
|
||||
When the completion handler is invoked, the stream is then
|
||||
ready to send and receive WebSocket protocol frames and
|
||||
messages.
|
||||
If the HTTP Upgrade request is invalid or cannot be satisfied,
|
||||
an HTTP response is sent indicating the reason and status code
|
||||
(typically 400, "Bad Request"). This counts as a failure, and
|
||||
the completion handler will be invoked with a suitable error
|
||||
code set.
|
||||
|
||||
@param req An object containing the HTTP Upgrade request.
|
||||
Ownership is not transferred, the implementation will not access
|
||||
this object from other threads.
|
||||
|
||||
@param handler The handler to be called when the request
|
||||
completes. Copies will be made of the handler as required. The
|
||||
equivalent function signature of the handler must be:
|
||||
@code void handler(
|
||||
error_code const& 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 `boost::asio::io_service::post`.
|
||||
*/
|
||||
template<class Body, class Allocator,
|
||||
template<
|
||||
class ResponseDecorator,
|
||||
class AcceptHandler>
|
||||
#if BOOST_BEAST_DOXYGEN
|
||||
void_or_deduced
|
||||
@ -2436,93 +2036,26 @@ public:
|
||||
async_return_type<
|
||||
AcceptHandler, void(error_code)>
|
||||
#endif
|
||||
async_accept(http::request<Body,
|
||||
http::basic_fields<Allocator>> const& req,
|
||||
AcceptHandler&& handler);
|
||||
async_accept_ex(
|
||||
ResponseDecorator const& decorator,
|
||||
AcceptHandler&& handler);
|
||||
|
||||
/** Start responding to a WebSocket HTTP Upgrade request.
|
||||
/** Start reading and responding to a WebSocket HTTP Upgrade request.
|
||||
|
||||
This function is used to asynchronously send the HTTP response
|
||||
to an HTTP request possibly containing a WebSocket Upgrade
|
||||
request. The function call always returns immediately. The
|
||||
asynchronous operation will continue until one of the following
|
||||
conditions is true:
|
||||
This function is used to asynchronously read an HTTP WebSocket
|
||||
Upgrade request and send the HTTP response. The function call
|
||||
always returns immediately. The asynchronous operation will
|
||||
continue until one of the following conditions is true:
|
||||
|
||||
@li The response finishes sending.
|
||||
@li The request is received and the response finishes sending.
|
||||
|
||||
@li An error occurs on the stream.
|
||||
|
||||
This operation is implemented in terms of one or more calls to
|
||||
the next layer's `async_write_some` functions, and is known as
|
||||
a <em>composed operation</em>. The program must ensure that the
|
||||
stream performs no other operations until this operation
|
||||
completes.
|
||||
|
||||
If the stream receives a valid HTTP WebSocket Upgrade request,
|
||||
an HTTP response is sent back indicating a successful upgrade.
|
||||
When the completion handler is invoked, the stream is then
|
||||
ready to send and receive WebSocket protocol frames and
|
||||
messages.
|
||||
If the HTTP Upgrade request is invalid or cannot be satisfied,
|
||||
an HTTP response is sent indicating the reason and status code
|
||||
(typically 400, "Bad Request"). This counts as a failure, and
|
||||
the completion handler will be invoked with a suitable error
|
||||
code set.
|
||||
|
||||
@param req An object containing the HTTP Upgrade request.
|
||||
Ownership is not transferred, the implementation will not access
|
||||
this object from other threads.
|
||||
|
||||
@param decorator A function object which will be called to modify
|
||||
the HTTP response object delivered by the implementation. This
|
||||
could be used to set the Server field, subprotocols, or other
|
||||
application or HTTP specific fields. The object will be called
|
||||
with this equivalent signature:
|
||||
@code void decorator(
|
||||
response_type& res
|
||||
); @endcode
|
||||
|
||||
@param handler The handler to be called when the request
|
||||
completes. Copies will be made of the handler as required. The
|
||||
equivalent function signature of the handler must be:
|
||||
@code void handler(
|
||||
error_code const& 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 `boost::asio::io_service::post`.
|
||||
*/
|
||||
template<class Body, class Allocator,
|
||||
class ResponseDecorator, class AcceptHandler>
|
||||
#if BOOST_BEAST_DOXYGEN
|
||||
void_or_deduced
|
||||
#else
|
||||
async_return_type<
|
||||
AcceptHandler, void(error_code)>
|
||||
#endif
|
||||
async_accept_ex(http::request<Body,
|
||||
http::basic_fields<Allocator>> const& req,
|
||||
ResponseDecorator const& decorator,
|
||||
AcceptHandler&& handler);
|
||||
|
||||
/** Start responding to a WebSocket HTTP Upgrade request.
|
||||
|
||||
This function is used to asynchronously send the HTTP response
|
||||
to an HTTP request possibly containing a WebSocket Upgrade
|
||||
request. The function call always returns immediately. The
|
||||
asynchronous operation will continue until one of the following
|
||||
conditions is true:
|
||||
|
||||
@li The response finishes sending.
|
||||
|
||||
@li An error occurs on the stream.
|
||||
|
||||
This operation is implemented in terms of one or more calls to
|
||||
the next layer's `async_write_some` functions, and is known as
|
||||
a <em>composed operation</em>. The program must ensure that the
|
||||
stream performs no other operations until this operation
|
||||
completes.
|
||||
the next layer's `async_read_some` and `async_write_some`
|
||||
functions, and is known as a <em>composed operation</em>. The
|
||||
program must ensure that the stream performs no other
|
||||
asynchronous operations until this operation completes.
|
||||
|
||||
If the stream receives a valid HTTP WebSocket Upgrade request,
|
||||
an HTTP response is sent back indicating a successful upgrade.
|
||||
@ -2536,15 +2069,12 @@ public:
|
||||
code set.
|
||||
|
||||
The implementation uses fixed size internal storage to
|
||||
copy the buffer. If the buffer is too large, the error
|
||||
receive the request. If the request is too large, the error
|
||||
@ref error::buffer_overflow will be indicated. Applications
|
||||
that wish to supply larger buffers should wrap the next layer
|
||||
in a @ref buffered_read_stream and store the buffer contents in
|
||||
the wrapper before calling accept.
|
||||
|
||||
@param req An object containing the HTTP Upgrade request.
|
||||
Ownership is not transferred, the implementation will not access
|
||||
this object from other threads.
|
||||
that wish to receive larger requests should first read the
|
||||
request using their own buffer and a suitable overload of
|
||||
@ref http::read or @ref http::async_read, then call @ref accept
|
||||
or @ref async_accept with the request.
|
||||
|
||||
@param buffers Caller provided data that has already been
|
||||
received on the stream. This may be used for implementations
|
||||
@ -2564,36 +2094,36 @@ public:
|
||||
this function. Invocation of the handler will be performed in a
|
||||
manner equivalent to using `boost::asio::io_service::post`.
|
||||
*/
|
||||
template<class Body, class Allocator,
|
||||
class ConstBufferSequence, class AcceptHandler>
|
||||
template<
|
||||
class ConstBufferSequence,
|
||||
class AcceptHandler>
|
||||
#if BOOST_BEAST_DOXYGEN
|
||||
void_or_deduced
|
||||
#else
|
||||
async_return_type<
|
||||
AcceptHandler, void(error_code)>
|
||||
typename std::enable_if<
|
||||
! http::detail::is_header<ConstBufferSequence>::value,
|
||||
async_return_type<AcceptHandler, void(error_code)>>::type
|
||||
#endif
|
||||
async_accept(http::request<Body,
|
||||
http::basic_fields<Allocator>> const& req,
|
||||
ConstBufferSequence const& buffers,
|
||||
AcceptHandler&& handler);
|
||||
async_accept(
|
||||
ConstBufferSequence const& buffers,
|
||||
AcceptHandler&& handler);
|
||||
|
||||
/** Start responding to a WebSocket HTTP Upgrade request.
|
||||
/** Start reading and responding to a WebSocket HTTP Upgrade request.
|
||||
|
||||
This function is used to asynchronously send the HTTP response
|
||||
to an HTTP request possibly containing a WebSocket Upgrade
|
||||
request. The function call always returns immediately. The
|
||||
asynchronous operation will continue until one of the following
|
||||
conditions is true:
|
||||
This function is used to asynchronously read an HTTP WebSocket
|
||||
Upgrade request and send the HTTP response. The function call
|
||||
always returns immediately. The asynchronous operation will
|
||||
continue until one of the following conditions is true:
|
||||
|
||||
@li The response finishes sending.
|
||||
@li The request is received and the response finishes sending.
|
||||
|
||||
@li An error occurs on the stream.
|
||||
|
||||
This operation is implemented in terms of one or more calls to
|
||||
the next layer's `async_write_some` functions, and is known as
|
||||
a <em>composed operation</em>. The program must ensure that the
|
||||
stream performs no other operations until this operation
|
||||
completes.
|
||||
the next layer's `async_read_some` and `async_write_some`
|
||||
functions, and is known as a <em>composed operation</em>. The
|
||||
program must ensure that the stream performs no other
|
||||
asynchronous operations until this operation completes.
|
||||
|
||||
If the stream receives a valid HTTP WebSocket Upgrade request,
|
||||
an HTTP response is sent back indicating a successful upgrade.
|
||||
@ -2607,15 +2137,12 @@ public:
|
||||
code set.
|
||||
|
||||
The implementation uses fixed size internal storage to
|
||||
copy the buffer. If the buffer is too large, the error
|
||||
receive the request. If the request is too large, the error
|
||||
@ref error::buffer_overflow will be indicated. Applications
|
||||
that wish to supply larger buffers should wrap the next layer
|
||||
in a @ref buffered_read_stream and store the buffer contents in
|
||||
the wrapper before calling accept.
|
||||
|
||||
@param req An object containing the HTTP Upgrade request.
|
||||
Ownership is not transferred, the implementation will not access
|
||||
this object from other threads.
|
||||
that wish to receive larger requests should first read the
|
||||
request using their own buffer and a suitable overload of
|
||||
@ref http::read or @ref http::async_read, then call @ref accept
|
||||
or @ref async_accept with the request.
|
||||
|
||||
@param buffers Caller provided data that has already been
|
||||
received on the stream. This may be used for implementations
|
||||
@ -2645,12 +2172,138 @@ public:
|
||||
manner equivalent to using `boost::asio::io_service::post`.
|
||||
*/
|
||||
template<
|
||||
class Body, class Allocator,
|
||||
class ConstBufferSequence,
|
||||
class ResponseDecorator,
|
||||
class AcceptHandler>
|
||||
#if BOOST_BEAST_DOXYGEN
|
||||
void_or_deduced
|
||||
#else
|
||||
typename std::enable_if<
|
||||
! http::detail::is_header<ConstBufferSequence>::value,
|
||||
async_return_type<AcceptHandler, void(error_code)>>::type
|
||||
#endif
|
||||
async_accept_ex(
|
||||
ConstBufferSequence const& buffers,
|
||||
ResponseDecorator const& decorator,
|
||||
AcceptHandler&& handler);
|
||||
|
||||
/** Start responding to a WebSocket HTTP Upgrade request.
|
||||
|
||||
This function is used to asynchronously send the HTTP response
|
||||
to an HTTP request possibly containing a WebSocket Upgrade
|
||||
request. The function call always returns immediately. The
|
||||
asynchronous operation will continue until one of the following
|
||||
conditions is true:
|
||||
|
||||
@li The response finishes sending.
|
||||
|
||||
@li An error occurs on the stream.
|
||||
|
||||
This operation is implemented in terms of one or more calls to
|
||||
the next layer's `async_write_some` functions, and is known as
|
||||
a <em>composed operation</em>. The program must ensure that the
|
||||
stream performs no other operations until this operation
|
||||
completes.
|
||||
|
||||
If the stream receives a valid HTTP WebSocket Upgrade request,
|
||||
an HTTP response is sent back indicating a successful upgrade.
|
||||
When the completion handler is invoked, the stream is then
|
||||
ready to send and receive WebSocket protocol frames and
|
||||
messages.
|
||||
If the HTTP Upgrade request is invalid or cannot be satisfied,
|
||||
an HTTP response is sent indicating the reason and status code
|
||||
(typically 400, "Bad Request"). This counts as a failure, and
|
||||
the completion handler will be invoked with a suitable error
|
||||
code set.
|
||||
|
||||
@param req An object containing the HTTP Upgrade request.
|
||||
Ownership is not transferred, the implementation will not access
|
||||
this object from other threads.
|
||||
|
||||
@param handler The handler to be called when the request
|
||||
completes. Copies will be made of the handler as required. The
|
||||
equivalent function signature of the handler must be:
|
||||
@code void handler(
|
||||
error_code const& 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 `boost::asio::io_service::post`.
|
||||
*/
|
||||
template<
|
||||
class Body, class Allocator,
|
||||
class AcceptHandler>
|
||||
#if BOOST_BEAST_DOXYGEN
|
||||
void_or_deduced
|
||||
#else
|
||||
async_return_type<
|
||||
AcceptHandler, void(error_code)>
|
||||
#endif
|
||||
async_accept(
|
||||
http::request<Body,
|
||||
http::basic_fields<Allocator>> const& req,
|
||||
AcceptHandler&& handler);
|
||||
|
||||
/** Start responding to a WebSocket HTTP Upgrade request.
|
||||
|
||||
This function is used to asynchronously send the HTTP response
|
||||
to an HTTP request possibly containing a WebSocket Upgrade
|
||||
request. The function call always returns immediately. The
|
||||
asynchronous operation will continue until one of the following
|
||||
conditions is true:
|
||||
|
||||
@li The response finishes sending.
|
||||
|
||||
@li An error occurs on the stream.
|
||||
|
||||
This operation is implemented in terms of one or more calls to
|
||||
the next layer's `async_write_some` functions, and is known as
|
||||
a <em>composed operation</em>. The program must ensure that the
|
||||
stream performs no other operations until this operation
|
||||
completes.
|
||||
|
||||
If the stream receives a valid HTTP WebSocket Upgrade request,
|
||||
an HTTP response is sent back indicating a successful upgrade.
|
||||
When the completion handler is invoked, the stream is then
|
||||
ready to send and receive WebSocket protocol frames and
|
||||
messages.
|
||||
If the HTTP Upgrade request is invalid or cannot be satisfied,
|
||||
an HTTP response is sent indicating the reason and status code
|
||||
(typically 400, "Bad Request"). This counts as a failure, and
|
||||
the completion handler will be invoked with a suitable error
|
||||
code set.
|
||||
|
||||
@param req An object containing the HTTP Upgrade request.
|
||||
Ownership is not transferred, the implementation will not access
|
||||
this object from other threads.
|
||||
|
||||
@param decorator A function object which will be called to modify
|
||||
the HTTP response object delivered by the implementation. This
|
||||
could be used to set the Server field, subprotocols, or other
|
||||
application or HTTP specific fields. The object will be called
|
||||
with this equivalent signature:
|
||||
@code void decorator(
|
||||
response_type& res
|
||||
); @endcode
|
||||
|
||||
@param handler The handler to be called when the request
|
||||
completes. Copies will be made of the handler as required. The
|
||||
equivalent function signature of the handler must be:
|
||||
@code void handler(
|
||||
error_code const& 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 `boost::asio::io_service::post`.
|
||||
*/
|
||||
template<
|
||||
class Body, class Allocator,
|
||||
class ResponseDecorator,
|
||||
class AcceptHandler>
|
||||
#if BOOST_BEAST_DOXYGEN
|
||||
void_or_deduced
|
||||
#else
|
||||
async_return_type<
|
||||
AcceptHandler, void(error_code)>
|
||||
@ -2658,7 +2311,6 @@ public:
|
||||
async_accept_ex(
|
||||
http::request<Body,
|
||||
http::basic_fields<Allocator>> const& req,
|
||||
ConstBufferSequence const& buffers,
|
||||
ResponseDecorator const& decorator,
|
||||
AcceptHandler&& handler);
|
||||
|
||||
|
@ -17,8 +17,6 @@
|
||||
#include <boost/beast/test/stream.hpp>
|
||||
#include <boost/beast/test/yield_to.hpp>
|
||||
#include <boost/beast/unit_test/suite.hpp>
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/asio/spawn.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
@ -409,15 +407,6 @@ public:
|
||||
ws.accept(req);
|
||||
}
|
||||
|
||||
template<class NextLayer, class Buffers>
|
||||
void
|
||||
accept(stream<NextLayer>& ws,
|
||||
http::request<http::empty_body> const& req,
|
||||
Buffers const& buffers) const
|
||||
{
|
||||
ws.accept(req, buffers);
|
||||
}
|
||||
|
||||
template<class NextLayer, class Decorator>
|
||||
void
|
||||
accept_ex(stream<NextLayer>& ws,
|
||||
@ -612,18 +601,6 @@ public:
|
||||
throw system_error{ec};
|
||||
}
|
||||
|
||||
template<class NextLayer, class Buffers>
|
||||
void
|
||||
accept(stream<NextLayer>& ws,
|
||||
http::request<http::empty_body> const& req,
|
||||
Buffers const& buffers) const
|
||||
{
|
||||
error_code ec;
|
||||
ws.async_accept(req, buffers, yield_[ec]);
|
||||
if(ec)
|
||||
throw system_error{ec};
|
||||
}
|
||||
|
||||
template<class NextLayer,
|
||||
class Decorator>
|
||||
void
|
||||
@ -877,6 +854,13 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
auto const big = []
|
||||
{
|
||||
std::string s;
|
||||
s += "X1: " + std::string(2000, '*') + "\r\n";
|
||||
return s;
|
||||
}();
|
||||
|
||||
// request in stream
|
||||
doTestLoop([&](test::stream& ts)
|
||||
{
|
||||
@ -894,6 +878,32 @@ public:
|
||||
// VFALCO validate contents of ws.next_layer().str?
|
||||
});
|
||||
|
||||
// request in stream, oversized
|
||||
{
|
||||
stream<test::stream> ws{ios_,
|
||||
"GET / HTTP/1.1\r\n"
|
||||
"Host: localhost\r\n"
|
||||
"Upgrade: websocket\r\n"
|
||||
"Connection: upgrade\r\n"
|
||||
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
|
||||
"Sec-WebSocket-Version: 13\r\n"
|
||||
+ big +
|
||||
"\r\n"};
|
||||
error_code ec = test::error::fail_error;
|
||||
try
|
||||
{
|
||||
c.accept(ws);
|
||||
fail("", __FILE__, __LINE__);
|
||||
}
|
||||
catch(system_error const& se)
|
||||
{
|
||||
// VFALCO Its the http error category...
|
||||
BEAST_EXPECTS(
|
||||
se.code() == http::error::buffer_overflow,
|
||||
se.code().message());
|
||||
}
|
||||
}
|
||||
|
||||
// request in stream, decorator
|
||||
doTestLoop([&](test::stream& ts)
|
||||
{
|
||||
@ -912,6 +922,32 @@ public:
|
||||
BEAST_EXPECT(called);
|
||||
});
|
||||
|
||||
// request in stream, decorator, oversized
|
||||
{
|
||||
stream<test::stream> ws{ios_,
|
||||
"GET / HTTP/1.1\r\n"
|
||||
"Host: localhost\r\n"
|
||||
"Upgrade: websocket\r\n"
|
||||
"Connection: upgrade\r\n"
|
||||
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
|
||||
"Sec-WebSocket-Version: 13\r\n"
|
||||
+ big +
|
||||
"\r\n"};
|
||||
try
|
||||
{
|
||||
bool called = false;
|
||||
c.accept_ex(ws, res_decorator{called});
|
||||
fail("", __FILE__, __LINE__);
|
||||
}
|
||||
catch(system_error const& se)
|
||||
{
|
||||
// VFALCO Its the http error category...
|
||||
BEAST_EXPECTS(
|
||||
se.code() == http::error::buffer_overflow,
|
||||
se.code().message());
|
||||
}
|
||||
}
|
||||
|
||||
// request in buffers
|
||||
doTestLoop([&](test::stream& ts)
|
||||
{
|
||||
@ -927,6 +963,31 @@ public:
|
||||
));
|
||||
});
|
||||
|
||||
// request in buffers, oversize
|
||||
{
|
||||
stream<test::stream> ws{ios_};
|
||||
try
|
||||
{
|
||||
c.accept(ws, boost::asio::buffer(
|
||||
"GET / HTTP/1.1\r\n"
|
||||
"Host: localhost\r\n"
|
||||
"Upgrade: websocket\r\n"
|
||||
"Connection: upgrade\r\n"
|
||||
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
|
||||
"Sec-WebSocket-Version: 13\r\n"
|
||||
+ big +
|
||||
"\r\n"
|
||||
));
|
||||
fail("", __FILE__, __LINE__);
|
||||
}
|
||||
catch(system_error const& se)
|
||||
{
|
||||
BEAST_EXPECTS(
|
||||
se.code() == error::buffer_overflow,
|
||||
se.code().message());
|
||||
}
|
||||
}
|
||||
|
||||
// request in buffers, decorator
|
||||
doTestLoop([&](test::stream& ts)
|
||||
{
|
||||
@ -944,6 +1005,32 @@ public:
|
||||
BEAST_EXPECT(called);
|
||||
});
|
||||
|
||||
// request in buffers, decorator, oversized
|
||||
{
|
||||
stream<test::stream> ws{ios_};
|
||||
try
|
||||
{
|
||||
bool called = false;
|
||||
c.accept_ex(ws, boost::asio::buffer(
|
||||
"GET / HTTP/1.1\r\n"
|
||||
"Host: localhost\r\n"
|
||||
"Upgrade: websocket\r\n"
|
||||
"Connection: upgrade\r\n"
|
||||
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
|
||||
"Sec-WebSocket-Version: 13\r\n"
|
||||
+ big +
|
||||
"\r\n"),
|
||||
res_decorator{called});
|
||||
fail("", __FILE__, __LINE__);
|
||||
}
|
||||
catch(system_error const& se)
|
||||
{
|
||||
BEAST_EXPECTS(
|
||||
se.code() == error::buffer_overflow,
|
||||
se.code().message());
|
||||
}
|
||||
}
|
||||
|
||||
// request in buffers and stream
|
||||
doTestLoop([&](test::stream& ts)
|
||||
{
|
||||
@ -962,6 +1049,31 @@ public:
|
||||
// VFALCO validate contents of ws.next_layer().str?
|
||||
});
|
||||
|
||||
// request in buffers and stream, oversized
|
||||
{
|
||||
stream<test::stream> ws{ios_,
|
||||
"Connection: upgrade\r\n"
|
||||
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
|
||||
"Sec-WebSocket-Version: 13\r\n"
|
||||
+ big +
|
||||
"\r\n"};
|
||||
try
|
||||
{
|
||||
c.accept(ws, sbuf(
|
||||
"GET / HTTP/1.1\r\n"
|
||||
"Host: localhost\r\n"
|
||||
"Upgrade: websocket\r\n"
|
||||
));
|
||||
fail("", __FILE__, __LINE__);
|
||||
}
|
||||
catch(system_error const& se)
|
||||
{
|
||||
BEAST_EXPECTS(
|
||||
se.code() == http::error::buffer_overflow,
|
||||
se.code().message());
|
||||
}
|
||||
}
|
||||
|
||||
// request in buffers and stream, decorator
|
||||
doTestLoop([&](test::stream& ts)
|
||||
{
|
||||
@ -981,6 +1093,32 @@ public:
|
||||
BEAST_EXPECT(called);
|
||||
});
|
||||
|
||||
// request in buffers and stream, decorator, oversize
|
||||
{
|
||||
stream<test::stream> ws{ios_,
|
||||
"Connection: upgrade\r\n"
|
||||
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
|
||||
"Sec-WebSocket-Version: 13\r\n"
|
||||
+ big +
|
||||
"\r\n"};
|
||||
try
|
||||
{
|
||||
bool called = false;
|
||||
c.accept_ex(ws, sbuf(
|
||||
"GET / HTTP/1.1\r\n"
|
||||
"Host: localhost\r\n"
|
||||
"Upgrade: websocket\r\n"),
|
||||
res_decorator{called});
|
||||
fail("", __FILE__, __LINE__);
|
||||
}
|
||||
catch(system_error const& se)
|
||||
{
|
||||
BEAST_EXPECTS(
|
||||
se.code() == http::error::buffer_overflow,
|
||||
se.code().message());
|
||||
}
|
||||
}
|
||||
|
||||
// request in message
|
||||
doTestLoop([&](test::stream& ts)
|
||||
{
|
||||
@ -1016,65 +1154,6 @@ public:
|
||||
BEAST_EXPECT(called);
|
||||
});
|
||||
|
||||
// request in message, close frame in buffers
|
||||
doTestLoop([&](test::stream& ts)
|
||||
{
|
||||
stream<test::stream&> ws{ts};
|
||||
request_type req;
|
||||
req.method(http::verb::get);
|
||||
req.target("/");
|
||||
req.version = 11;
|
||||
req.insert(http::field::host, "localhost");
|
||||
req.insert(http::field::upgrade, "websocket");
|
||||
req.insert(http::field::connection, "upgrade");
|
||||
req.insert(http::field::sec_websocket_key, "dGhlIHNhbXBsZSBub25jZQ==");
|
||||
req.insert(http::field::sec_websocket_version, "13");
|
||||
c.accept(ws, req, cbuf(
|
||||
0x88, 0x82, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x17));
|
||||
try
|
||||
{
|
||||
static_buffer<1> b;
|
||||
c.read(ws, b);
|
||||
fail("success", __FILE__, __LINE__);
|
||||
}
|
||||
catch(system_error const& e)
|
||||
{
|
||||
if(e.code() != websocket::error::closed)
|
||||
throw;
|
||||
}
|
||||
});
|
||||
|
||||
// request in message, close frame in buffers, decorator
|
||||
doTestLoop([&](test::stream& ts)
|
||||
{
|
||||
stream<test::stream&> ws{ts};
|
||||
request_type req;
|
||||
req.method(http::verb::get);
|
||||
req.target("/");
|
||||
req.version = 11;
|
||||
req.insert(http::field::host, "localhost");
|
||||
req.insert(http::field::upgrade, "websocket");
|
||||
req.insert(http::field::connection, "upgrade");
|
||||
req.insert(http::field::sec_websocket_key, "dGhlIHNhbXBsZSBub25jZQ==");
|
||||
req.insert(http::field::sec_websocket_version, "13");
|
||||
bool called = false;
|
||||
c.accept_ex(ws, req, cbuf(
|
||||
0x88, 0x82, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x17),
|
||||
res_decorator{called});
|
||||
BEAST_EXPECT(called);
|
||||
try
|
||||
{
|
||||
static_buffer<1> b;
|
||||
c.read(ws, b);
|
||||
fail("success", __FILE__, __LINE__);
|
||||
}
|
||||
catch(system_error const& e)
|
||||
{
|
||||
if(e.code() != websocket::error::closed)
|
||||
throw;
|
||||
}
|
||||
});
|
||||
|
||||
// request in message, close frame in stream
|
||||
doTestLoop([&](test::stream& ts)
|
||||
{
|
||||
@ -1103,35 +1182,6 @@ public:
|
||||
}
|
||||
});
|
||||
|
||||
// request in message, close frame in stream and buffers
|
||||
doTestLoop([&](test::stream& ts)
|
||||
{
|
||||
stream<test::stream&> ws{ts};
|
||||
request_type req;
|
||||
req.method(http::verb::get);
|
||||
req.target("/");
|
||||
req.version = 11;
|
||||
req.insert(http::field::host, "localhost");
|
||||
req.insert(http::field::upgrade, "websocket");
|
||||
req.insert(http::field::connection, "upgrade");
|
||||
req.insert(http::field::sec_websocket_key, "dGhlIHNhbXBsZSBub25jZQ==");
|
||||
req.insert(http::field::sec_websocket_version, "13");
|
||||
ts.str("xff\xff\xfc\x17");
|
||||
c.accept(ws, req, cbuf(
|
||||
0x88, 0x82, 0xff, 0xff));
|
||||
try
|
||||
{
|
||||
static_buffer<1> b;
|
||||
c.read(ws, b);
|
||||
fail("success", __FILE__, __LINE__);
|
||||
}
|
||||
catch(system_error const& e)
|
||||
{
|
||||
if(e.code() != websocket::error::closed)
|
||||
throw;
|
||||
}
|
||||
});
|
||||
|
||||
// failed handshake (missing Sec-WebSocket-Key)
|
||||
doTestLoop([&](test::stream& ts)
|
||||
{
|
||||
@ -1158,6 +1208,24 @@ public:
|
||||
throw;
|
||||
}
|
||||
});
|
||||
|
||||
// Closed by client
|
||||
{
|
||||
stream<test::stream> ws{ios_};
|
||||
ws.next_layer().remote().close();
|
||||
try
|
||||
{
|
||||
c.accept(ws);
|
||||
fail("success", __FILE__, __LINE__);
|
||||
}
|
||||
catch(system_error const& e)
|
||||
{
|
||||
if(! BEAST_EXPECTS(
|
||||
e.code() == error::closed,
|
||||
e.code().message()))
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -2059,14 +2127,15 @@ public:
|
||||
stream<socket_type&>>::value);
|
||||
|
||||
log << "sizeof(websocket::stream) == " <<
|
||||
sizeof(websocket::stream<boost::asio::ip::tcp::socket&>) << std::endl;
|
||||
sizeof(websocket::stream<test::stream&>) << std::endl;
|
||||
|
||||
testAccept();
|
||||
|
||||
permessage_deflate pmd;
|
||||
pmd.client_enable = false;
|
||||
pmd.server_enable = false;
|
||||
|
||||
testOptions();
|
||||
testAccept();
|
||||
testHandshake();
|
||||
testBadHandshakes();
|
||||
testBadResponses();
|
||||
|
Reference in New Issue
Block a user