mirror of
https://github.com/boostorg/beast.git
synced 2025-07-31 21:34:46 +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
|
* 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:
|
Version 108:
|
||||||
|
@@ -19,6 +19,7 @@
|
|||||||
#include <boost/beast/core/buffer_prefix.hpp>
|
#include <boost/beast/core/buffer_prefix.hpp>
|
||||||
#include <boost/beast/core/handler_ptr.hpp>
|
#include <boost/beast/core/handler_ptr.hpp>
|
||||||
#include <boost/beast/core/detail/type_traits.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_alloc_hook.hpp>
|
||||||
#include <boost/asio/handler_continuation_hook.hpp>
|
#include <boost/asio/handler_continuation_hook.hpp>
|
||||||
#include <boost/asio/handler_invoke_hook.hpp>
|
#include <boost/asio/handler_invoke_hook.hpp>
|
||||||
@@ -35,12 +36,12 @@ namespace websocket {
|
|||||||
template<class NextLayer>
|
template<class NextLayer>
|
||||||
template<class Handler>
|
template<class Handler>
|
||||||
class stream<NextLayer>::response_op
|
class stream<NextLayer>::response_op
|
||||||
|
: public boost::asio::coroutine
|
||||||
{
|
{
|
||||||
struct data
|
struct data
|
||||||
{
|
{
|
||||||
stream<NextLayer>& ws;
|
stream<NextLayer>& ws;
|
||||||
response_type res;
|
response_type res;
|
||||||
int step = 0;
|
|
||||||
|
|
||||||
template<class Body, class Allocator, class Decorator>
|
template<class Body, class Allocator, class Decorator>
|
||||||
data(Handler&, stream<NextLayer>& ws_, http::request<
|
data(Handler&, stream<NextLayer>& ws_, http::request<
|
||||||
@@ -66,10 +67,7 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Buffers>
|
void operator()(error_code ec = {});
|
||||||
void operator()(Buffers const& buffers);
|
|
||||||
|
|
||||||
void operator()(error_code ec);
|
|
||||||
|
|
||||||
friend
|
friend
|
||||||
void* asio_handler_allocate(
|
void* asio_handler_allocate(
|
||||||
@@ -90,10 +88,11 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
friend
|
friend
|
||||||
bool asio_handler_is_continuation(response_op*)
|
bool asio_handler_is_continuation(response_op* op)
|
||||||
{
|
{
|
||||||
// VFALCO This will go away in Net-TS
|
using boost::asio::asio_handler_is_continuation;
|
||||||
return false;
|
return asio_handler_is_continuation(
|
||||||
|
std::addressof(op->d_.handler()));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Function>
|
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 NextLayer>
|
||||||
template<class Handler>
|
template<class Handler>
|
||||||
void
|
void
|
||||||
@@ -145,18 +113,13 @@ response_op<Handler>::
|
|||||||
operator()(error_code ec)
|
operator()(error_code ec)
|
||||||
{
|
{
|
||||||
auto& d = *d_;
|
auto& d = *d_;
|
||||||
switch(d.step)
|
BOOST_ASIO_CORO_REENTER(*this)
|
||||||
{
|
{
|
||||||
case 0:
|
// Send response
|
||||||
// send response
|
BOOST_ASIO_CORO_YIELD
|
||||||
d.step = 1;
|
|
||||||
http::async_write(d.ws.next_layer(),
|
http::async_write(d.ws.next_layer(),
|
||||||
d.res, std::move(*this));
|
d.res, std::move(*this));
|
||||||
return;
|
if(! ec && d.res.result() !=
|
||||||
|
|
||||||
// sent response
|
|
||||||
case 1:
|
|
||||||
if(d.res.result() !=
|
|
||||||
http::status::switching_protocols)
|
http::status::switching_protocols)
|
||||||
ec = error::handshake_failed;
|
ec = error::handshake_failed;
|
||||||
if(! ec)
|
if(! ec)
|
||||||
@@ -164,13 +127,8 @@ operator()(error_code ec)
|
|||||||
pmd_read(d.ws.pmd_config_, d.res);
|
pmd_read(d.ws.pmd_config_, d.res);
|
||||||
d.ws.open(role_type::server);
|
d.ws.open(role_type::server);
|
||||||
}
|
}
|
||||||
break;
|
d_.invoke(ec);
|
||||||
|
|
||||||
// call handler
|
|
||||||
case 2:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
d_.invoke(ec);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@@ -180,13 +138,13 @@ operator()(error_code ec)
|
|||||||
template<class NextLayer>
|
template<class NextLayer>
|
||||||
template<class Decorator, class Handler>
|
template<class Decorator, class Handler>
|
||||||
class stream<NextLayer>::accept_op
|
class stream<NextLayer>::accept_op
|
||||||
|
: public boost::asio::coroutine
|
||||||
{
|
{
|
||||||
struct data
|
struct data
|
||||||
{
|
{
|
||||||
stream<NextLayer>& ws;
|
stream<NextLayer>& ws;
|
||||||
Decorator decorator;
|
Decorator decorator;
|
||||||
http::request_parser<http::empty_body> p;
|
http::request_parser<http::empty_body> p;
|
||||||
int step = 0;
|
|
||||||
data(Handler&, stream<NextLayer>& ws_,
|
data(Handler&, stream<NextLayer>& ws_,
|
||||||
Decorator const& decorator_)
|
Decorator const& decorator_)
|
||||||
: ws(ws_)
|
: ws(ws_)
|
||||||
@@ -210,9 +168,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<class Buffers>
|
template<class Buffers>
|
||||||
void operator()(Buffers const& buffers);
|
void run(Buffers const& buffers);
|
||||||
|
|
||||||
void operator()(error_code ec);
|
void operator()(error_code ec = {});
|
||||||
|
|
||||||
friend
|
friend
|
||||||
void* asio_handler_allocate(
|
void* asio_handler_allocate(
|
||||||
@@ -256,7 +214,7 @@ template<class Buffers>
|
|||||||
void
|
void
|
||||||
stream<NextLayer>::
|
stream<NextLayer>::
|
||||||
accept_op<Decorator, Handler>::
|
accept_op<Decorator, Handler>::
|
||||||
operator()(Buffers const& buffers)
|
run(Buffers const& buffers)
|
||||||
{
|
{
|
||||||
using boost::asio::buffer_copy;
|
using boost::asio::buffer_copy;
|
||||||
using boost::asio::buffer_size;
|
using boost::asio::buffer_size;
|
||||||
@@ -271,10 +229,8 @@ operator()(Buffers const& buffers)
|
|||||||
}
|
}
|
||||||
catch(std::length_error const&)
|
catch(std::length_error const&)
|
||||||
{
|
{
|
||||||
d.step = 2;
|
|
||||||
ec = error::buffer_overflow;
|
ec = error::buffer_overflow;
|
||||||
return d.ws.get_io_service().post(
|
return (*this)(ec);
|
||||||
bind_handler(std::move(*this), ec));
|
|
||||||
}
|
}
|
||||||
d.ws.rd_.buf.commit(
|
d.ws.rd_.buf.commit(
|
||||||
buffer_copy(*mb, buffers));
|
buffer_copy(*mb, buffers));
|
||||||
@@ -289,40 +245,45 @@ accept_op<Decorator, Handler>::
|
|||||||
operator()(error_code ec)
|
operator()(error_code ec)
|
||||||
{
|
{
|
||||||
auto& d = *d_;
|
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)
|
if(ec)
|
||||||
break;
|
{
|
||||||
// Arguments from our step must be
|
BOOST_ASIO_CORO_YIELD
|
||||||
// moved to the stack before releasing
|
d.ws.get_io_service().post(
|
||||||
// the handler.
|
bind_handler(std::move(*this), ec));
|
||||||
auto& ws = d.ws;
|
}
|
||||||
auto const req = d.p.release();
|
else
|
||||||
auto const decorator = d.decorator;
|
{
|
||||||
#if 1
|
BOOST_ASIO_CORO_YIELD
|
||||||
return response_op<Handler>{
|
http::async_read(
|
||||||
d_.release_handler(),
|
d.ws.next_layer(), d.ws.rd_.buf,
|
||||||
ws, req, decorator}(ec);
|
d.p, std::move(*this));
|
||||||
#else
|
if(ec == http::error::end_of_stream)
|
||||||
// VFALCO This *should* work but breaks
|
ec = error::closed;
|
||||||
// coroutine invariants in the unit test.
|
if(! ec)
|
||||||
// Also it calls reset() when it shouldn't.
|
{
|
||||||
return ws.async_accept_ex(
|
// Arguments from our step must be
|
||||||
req, decorator, d_.release_handler());
|
// moved to the stack before releasing
|
||||||
#endif
|
// 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 NextLayer>
|
||||||
template<
|
template<
|
||||||
class ConstBufferSequence, class ResponseDecorator>
|
class ConstBufferSequence,
|
||||||
|
class ResponseDecorator>
|
||||||
typename std::enable_if<! http::detail::is_header<
|
typename std::enable_if<! http::detail::is_header<
|
||||||
ConstBufferSequence>::value>::type
|
ConstBufferSequence>::value>::type
|
||||||
stream<NextLayer>::
|
stream<NextLayer>::
|
||||||
accept_ex(ConstBufferSequence const& buffers,
|
accept_ex(
|
||||||
|
ConstBufferSequence const& buffers,
|
||||||
ResponseDecorator const &decorator)
|
ResponseDecorator const &decorator)
|
||||||
{
|
{
|
||||||
static_assert(is_sync_stream<next_layer_type>::value,
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
@@ -429,30 +392,45 @@ template<class ConstBufferSequence>
|
|||||||
typename std::enable_if<! http::detail::is_header<
|
typename std::enable_if<! http::detail::is_header<
|
||||||
ConstBufferSequence>::value>::type
|
ConstBufferSequence>::value>::type
|
||||||
stream<NextLayer>::
|
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,
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
"SyncStream requirements not met");
|
"SyncStream requirements not met");
|
||||||
static_assert(is_const_buffer_sequence<
|
static_assert(is_const_buffer_sequence<
|
||||||
ConstBufferSequence>::value,
|
ConstBufferSequence>::value,
|
||||||
"ConstBufferSequence requirements not met");
|
"ConstBufferSequence requirements not met");
|
||||||
reset();
|
|
||||||
using boost::asio::buffer_copy;
|
using boost::asio::buffer_copy;
|
||||||
using boost::asio::buffer_size;
|
using boost::asio::buffer_size;
|
||||||
rd_.buf.commit(buffer_copy(
|
reset();
|
||||||
rd_.buf.prepare(
|
boost::optional<typename
|
||||||
buffer_size(buffers)), buffers));
|
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);
|
do_accept(&default_decorate_res, ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer>
|
||||||
template<
|
template<
|
||||||
class ConstBufferSequence, class ResponseDecorator>
|
class ConstBufferSequence,
|
||||||
|
class ResponseDecorator>
|
||||||
typename std::enable_if<! http::detail::is_header<
|
typename std::enable_if<! http::detail::is_header<
|
||||||
ConstBufferSequence>::value>::type
|
ConstBufferSequence>::value>::type
|
||||||
stream<NextLayer>::
|
stream<NextLayer>::
|
||||||
accept_ex(ConstBufferSequence const& buffers,
|
accept_ex(
|
||||||
ResponseDecorator const& decorator, error_code& ec)
|
ConstBufferSequence const& buffers,
|
||||||
|
ResponseDecorator const& decorator,
|
||||||
|
error_code& ec)
|
||||||
{
|
{
|
||||||
static_assert(is_sync_stream<next_layer_type>::value,
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
"SyncStream requirements not met");
|
"SyncStream requirements not met");
|
||||||
@@ -462,12 +440,22 @@ accept_ex(ConstBufferSequence const& buffers,
|
|||||||
static_assert(is_const_buffer_sequence<
|
static_assert(is_const_buffer_sequence<
|
||||||
ConstBufferSequence>::value,
|
ConstBufferSequence>::value,
|
||||||
"ConstBufferSequence requirements not met");
|
"ConstBufferSequence requirements not met");
|
||||||
reset();
|
|
||||||
using boost::asio::buffer_copy;
|
using boost::asio::buffer_copy;
|
||||||
using boost::asio::buffer_size;
|
using boost::asio::buffer_size;
|
||||||
rd_.buf.commit(buffer_copy(
|
reset();
|
||||||
rd_.buf.prepare(
|
boost::optional<typename
|
||||||
buffer_size(buffers)), buffers));
|
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);
|
do_accept(decorator, ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -475,8 +463,9 @@ template<class NextLayer>
|
|||||||
template<class Body, class Allocator>
|
template<class Body, class Allocator>
|
||||||
void
|
void
|
||||||
stream<NextLayer>::
|
stream<NextLayer>::
|
||||||
accept(http::request<Body,
|
accept(
|
||||||
http::basic_fields<Allocator>> const& req)
|
http::request<Body,
|
||||||
|
http::basic_fields<Allocator>> const& req)
|
||||||
{
|
{
|
||||||
static_assert(is_sync_stream<next_layer_type>::value,
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
"SyncStream requirements not met");
|
"SyncStream requirements not met");
|
||||||
@@ -487,12 +476,14 @@ accept(http::request<Body,
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer>
|
||||||
template<class Body,
|
template<
|
||||||
class Allocator, class ResponseDecorator>
|
class Body, class Allocator,
|
||||||
|
class ResponseDecorator>
|
||||||
void
|
void
|
||||||
stream<NextLayer>::
|
stream<NextLayer>::
|
||||||
accept_ex(http::request<Body,
|
accept_ex(
|
||||||
http::basic_fields<Allocator>> const& req,
|
http::request<Body,
|
||||||
|
http::basic_fields<Allocator>> const& req,
|
||||||
ResponseDecorator const& decorator)
|
ResponseDecorator const& decorator)
|
||||||
{
|
{
|
||||||
static_assert(is_sync_stream<next_layer_type>::value,
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
@@ -510,9 +501,10 @@ template<class NextLayer>
|
|||||||
template<class Body, class Allocator>
|
template<class Body, class Allocator>
|
||||||
void
|
void
|
||||||
stream<NextLayer>::
|
stream<NextLayer>::
|
||||||
accept(http::request<Body,
|
accept(
|
||||||
http::basic_fields<Allocator>> const& req,
|
http::request<Body,
|
||||||
error_code& ec)
|
http::basic_fields<Allocator>> const& req,
|
||||||
|
error_code& ec)
|
||||||
{
|
{
|
||||||
static_assert(is_sync_stream<next_layer_type>::value,
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
"SyncStream requirements not met");
|
"SyncStream requirements not met");
|
||||||
@@ -521,13 +513,16 @@ accept(http::request<Body,
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer>
|
||||||
template<class Body, class Allocator,
|
template<
|
||||||
|
class Body, class Allocator,
|
||||||
class ResponseDecorator>
|
class ResponseDecorator>
|
||||||
void
|
void
|
||||||
stream<NextLayer>::
|
stream<NextLayer>::
|
||||||
accept_ex(http::request<Body,
|
accept_ex(
|
||||||
http::basic_fields<Allocator>> const& req,
|
http::request<Body,
|
||||||
ResponseDecorator const& decorator, error_code& ec)
|
http::basic_fields<Allocator>> const& req,
|
||||||
|
ResponseDecorator const& decorator,
|
||||||
|
error_code& ec)
|
||||||
{
|
{
|
||||||
static_assert(is_sync_stream<next_layer_type>::value,
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
"SyncStream requirements not met");
|
"SyncStream requirements not met");
|
||||||
@@ -538,101 +533,6 @@ accept_ex(http::request<Body,
|
|||||||
do_accept(req, decorator, ec);
|
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>
|
template<class NextLayer>
|
||||||
@@ -709,7 +609,7 @@ async_accept(
|
|||||||
handler_type<AcceptHandler, void(error_code)>>{
|
handler_type<AcceptHandler, void(error_code)>>{
|
||||||
init.completion_handler,
|
init.completion_handler,
|
||||||
*this,
|
*this,
|
||||||
&default_decorate_res}(buffers);
|
&default_decorate_res}.run(buffers);
|
||||||
return init.result.get();
|
return init.result.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -743,7 +643,7 @@ async_accept_ex(
|
|||||||
handler_type<AcceptHandler, void(error_code)>>{
|
handler_type<AcceptHandler, void(error_code)>>{
|
||||||
init.completion_handler,
|
init.completion_handler,
|
||||||
*this,
|
*this,
|
||||||
decorator}(buffers);
|
decorator}.run(buffers);
|
||||||
return init.result.get();
|
return init.result.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -768,7 +668,7 @@ async_accept(
|
|||||||
init.completion_handler,
|
init.completion_handler,
|
||||||
*this,
|
*this,
|
||||||
req,
|
req,
|
||||||
&default_decorate_res}({});
|
&default_decorate_res}();
|
||||||
return init.result.get();
|
return init.result.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -798,73 +698,7 @@ async_accept_ex(
|
|||||||
init.completion_handler,
|
init.completion_handler,
|
||||||
*this,
|
*this,
|
||||||
req,
|
req,
|
||||||
decorator}({});
|
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);
|
|
||||||
return init.result.get();
|
return init.result.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1915,212 +1915,6 @@ public:
|
|||||||
ResponseDecorator const& decorator,
|
ResponseDecorator const& decorator,
|
||||||
error_code& ec);
|
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.
|
/** Start reading and responding to a WebSocket HTTP Upgrade request.
|
||||||
|
|
||||||
This function is used to asynchronously read an HTTP WebSocket
|
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
|
this function. Invocation of the handler will be performed in a
|
||||||
manner equivalent to using `boost::asio::io_service::post`.
|
manner equivalent to using `boost::asio::io_service::post`.
|
||||||
*/
|
*/
|
||||||
template<class ResponseDecorator, class AcceptHandler>
|
template<
|
||||||
#if BOOST_BEAST_DOXYGEN
|
class ResponseDecorator,
|
||||||
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,
|
|
||||||
class AcceptHandler>
|
class AcceptHandler>
|
||||||
#if BOOST_BEAST_DOXYGEN
|
#if BOOST_BEAST_DOXYGEN
|
||||||
void_or_deduced
|
void_or_deduced
|
||||||
@@ -2436,93 +2036,26 @@ public:
|
|||||||
async_return_type<
|
async_return_type<
|
||||||
AcceptHandler, void(error_code)>
|
AcceptHandler, void(error_code)>
|
||||||
#endif
|
#endif
|
||||||
async_accept(http::request<Body,
|
async_accept_ex(
|
||||||
http::basic_fields<Allocator>> const& req,
|
ResponseDecorator const& decorator,
|
||||||
AcceptHandler&& handler);
|
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
|
This function is used to asynchronously read an HTTP WebSocket
|
||||||
to an HTTP request possibly containing a WebSocket Upgrade
|
Upgrade request and send the HTTP response. The function call
|
||||||
request. The function call always returns immediately. The
|
always returns immediately. The asynchronous operation will
|
||||||
asynchronous operation will continue until one of the following
|
continue until one of the following conditions is true:
|
||||||
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.
|
@li An error occurs on the stream.
|
||||||
|
|
||||||
This operation is implemented in terms of one or more calls to
|
This operation is implemented in terms of one or more calls to
|
||||||
the next layer's `async_write_some` functions, and is known as
|
the next layer's `async_read_some` and `async_write_some`
|
||||||
a <em>composed operation</em>. The program must ensure that the
|
functions, and is known as a <em>composed operation</em>. The
|
||||||
stream performs no other operations until this operation
|
program must ensure that the stream performs no other
|
||||||
completes.
|
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.
|
|
||||||
|
|
||||||
@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.
|
|
||||||
|
|
||||||
If the stream receives a valid HTTP WebSocket Upgrade request,
|
If the stream receives a valid HTTP WebSocket Upgrade request,
|
||||||
an HTTP response is sent back indicating a successful upgrade.
|
an HTTP response is sent back indicating a successful upgrade.
|
||||||
@@ -2536,15 +2069,12 @@ public:
|
|||||||
code set.
|
code set.
|
||||||
|
|
||||||
The implementation uses fixed size internal storage to
|
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
|
@ref error::buffer_overflow will be indicated. Applications
|
||||||
that wish to supply larger buffers should wrap the next layer
|
that wish to receive larger requests should first read the
|
||||||
in a @ref buffered_read_stream and store the buffer contents in
|
request using their own buffer and a suitable overload of
|
||||||
the wrapper before calling accept.
|
@ref http::read or @ref http::async_read, then call @ref accept
|
||||||
|
or @ref async_accept with the request.
|
||||||
@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
|
@param buffers Caller provided data that has already been
|
||||||
received on the stream. This may be used for implementations
|
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
|
this function. Invocation of the handler will be performed in a
|
||||||
manner equivalent to using `boost::asio::io_service::post`.
|
manner equivalent to using `boost::asio::io_service::post`.
|
||||||
*/
|
*/
|
||||||
template<class Body, class Allocator,
|
template<
|
||||||
class ConstBufferSequence, class AcceptHandler>
|
class ConstBufferSequence,
|
||||||
|
class AcceptHandler>
|
||||||
#if BOOST_BEAST_DOXYGEN
|
#if BOOST_BEAST_DOXYGEN
|
||||||
void_or_deduced
|
void_or_deduced
|
||||||
#else
|
#else
|
||||||
async_return_type<
|
typename std::enable_if<
|
||||||
AcceptHandler, void(error_code)>
|
! http::detail::is_header<ConstBufferSequence>::value,
|
||||||
|
async_return_type<AcceptHandler, void(error_code)>>::type
|
||||||
#endif
|
#endif
|
||||||
async_accept(http::request<Body,
|
async_accept(
|
||||||
http::basic_fields<Allocator>> const& req,
|
ConstBufferSequence const& buffers,
|
||||||
ConstBufferSequence const& buffers,
|
AcceptHandler&& handler);
|
||||||
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
|
This function is used to asynchronously read an HTTP WebSocket
|
||||||
to an HTTP request possibly containing a WebSocket Upgrade
|
Upgrade request and send the HTTP response. The function call
|
||||||
request. The function call always returns immediately. The
|
always returns immediately. The asynchronous operation will
|
||||||
asynchronous operation will continue until one of the following
|
continue until one of the following conditions is true:
|
||||||
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.
|
@li An error occurs on the stream.
|
||||||
|
|
||||||
This operation is implemented in terms of one or more calls to
|
This operation is implemented in terms of one or more calls to
|
||||||
the next layer's `async_write_some` functions, and is known as
|
the next layer's `async_read_some` and `async_write_some`
|
||||||
a <em>composed operation</em>. The program must ensure that the
|
functions, and is known as a <em>composed operation</em>. The
|
||||||
stream performs no other operations until this operation
|
program must ensure that the stream performs no other
|
||||||
completes.
|
asynchronous operations until this operation completes.
|
||||||
|
|
||||||
If the stream receives a valid HTTP WebSocket Upgrade request,
|
If the stream receives a valid HTTP WebSocket Upgrade request,
|
||||||
an HTTP response is sent back indicating a successful upgrade.
|
an HTTP response is sent back indicating a successful upgrade.
|
||||||
@@ -2607,15 +2137,12 @@ public:
|
|||||||
code set.
|
code set.
|
||||||
|
|
||||||
The implementation uses fixed size internal storage to
|
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
|
@ref error::buffer_overflow will be indicated. Applications
|
||||||
that wish to supply larger buffers should wrap the next layer
|
that wish to receive larger requests should first read the
|
||||||
in a @ref buffered_read_stream and store the buffer contents in
|
request using their own buffer and a suitable overload of
|
||||||
the wrapper before calling accept.
|
@ref http::read or @ref http::async_read, then call @ref accept
|
||||||
|
or @ref async_accept with the request.
|
||||||
@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
|
@param buffers Caller provided data that has already been
|
||||||
received on the stream. This may be used for implementations
|
received on the stream. This may be used for implementations
|
||||||
@@ -2645,12 +2172,138 @@ public:
|
|||||||
manner equivalent to using `boost::asio::io_service::post`.
|
manner equivalent to using `boost::asio::io_service::post`.
|
||||||
*/
|
*/
|
||||||
template<
|
template<
|
||||||
class Body, class Allocator,
|
|
||||||
class ConstBufferSequence,
|
class ConstBufferSequence,
|
||||||
class ResponseDecorator,
|
class ResponseDecorator,
|
||||||
class AcceptHandler>
|
class AcceptHandler>
|
||||||
#if BOOST_BEAST_DOXYGEN
|
#if BOOST_BEAST_DOXYGEN
|
||||||
void_or_deduced
|
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
|
#else
|
||||||
async_return_type<
|
async_return_type<
|
||||||
AcceptHandler, void(error_code)>
|
AcceptHandler, void(error_code)>
|
||||||
@@ -2658,7 +2311,6 @@ public:
|
|||||||
async_accept_ex(
|
async_accept_ex(
|
||||||
http::request<Body,
|
http::request<Body,
|
||||||
http::basic_fields<Allocator>> const& req,
|
http::basic_fields<Allocator>> const& req,
|
||||||
ConstBufferSequence const& buffers,
|
|
||||||
ResponseDecorator const& decorator,
|
ResponseDecorator const& decorator,
|
||||||
AcceptHandler&& handler);
|
AcceptHandler&& handler);
|
||||||
|
|
||||||
|
@@ -17,8 +17,6 @@
|
|||||||
#include <boost/beast/test/stream.hpp>
|
#include <boost/beast/test/stream.hpp>
|
||||||
#include <boost/beast/test/yield_to.hpp>
|
#include <boost/beast/test/yield_to.hpp>
|
||||||
#include <boost/beast/unit_test/suite.hpp>
|
#include <boost/beast/unit_test/suite.hpp>
|
||||||
#include <boost/asio.hpp>
|
|
||||||
#include <boost/asio/spawn.hpp>
|
|
||||||
#include <boost/optional.hpp>
|
#include <boost/optional.hpp>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
@@ -409,15 +407,6 @@ public:
|
|||||||
ws.accept(req);
|
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>
|
template<class NextLayer, class Decorator>
|
||||||
void
|
void
|
||||||
accept_ex(stream<NextLayer>& ws,
|
accept_ex(stream<NextLayer>& ws,
|
||||||
@@ -612,18 +601,6 @@ public:
|
|||||||
throw system_error{ec};
|
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,
|
template<class NextLayer,
|
||||||
class Decorator>
|
class Decorator>
|
||||||
void
|
void
|
||||||
@@ -877,6 +854,13 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
auto const big = []
|
||||||
|
{
|
||||||
|
std::string s;
|
||||||
|
s += "X1: " + std::string(2000, '*') + "\r\n";
|
||||||
|
return s;
|
||||||
|
}();
|
||||||
|
|
||||||
// request in stream
|
// request in stream
|
||||||
doTestLoop([&](test::stream& ts)
|
doTestLoop([&](test::stream& ts)
|
||||||
{
|
{
|
||||||
@@ -894,6 +878,32 @@ public:
|
|||||||
// VFALCO validate contents of ws.next_layer().str?
|
// 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
|
// request in stream, decorator
|
||||||
doTestLoop([&](test::stream& ts)
|
doTestLoop([&](test::stream& ts)
|
||||||
{
|
{
|
||||||
@@ -912,6 +922,32 @@ public:
|
|||||||
BEAST_EXPECT(called);
|
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
|
// request in buffers
|
||||||
doTestLoop([&](test::stream& ts)
|
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
|
// request in buffers, decorator
|
||||||
doTestLoop([&](test::stream& ts)
|
doTestLoop([&](test::stream& ts)
|
||||||
{
|
{
|
||||||
@@ -944,6 +1005,32 @@ public:
|
|||||||
BEAST_EXPECT(called);
|
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
|
// request in buffers and stream
|
||||||
doTestLoop([&](test::stream& ts)
|
doTestLoop([&](test::stream& ts)
|
||||||
{
|
{
|
||||||
@@ -962,6 +1049,31 @@ public:
|
|||||||
// VFALCO validate contents of ws.next_layer().str?
|
// 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
|
// request in buffers and stream, decorator
|
||||||
doTestLoop([&](test::stream& ts)
|
doTestLoop([&](test::stream& ts)
|
||||||
{
|
{
|
||||||
@@ -981,6 +1093,32 @@ public:
|
|||||||
BEAST_EXPECT(called);
|
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
|
// request in message
|
||||||
doTestLoop([&](test::stream& ts)
|
doTestLoop([&](test::stream& ts)
|
||||||
{
|
{
|
||||||
@@ -1016,65 +1154,6 @@ public:
|
|||||||
BEAST_EXPECT(called);
|
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
|
// request in message, close frame in stream
|
||||||
doTestLoop([&](test::stream& ts)
|
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)
|
// failed handshake (missing Sec-WebSocket-Key)
|
||||||
doTestLoop([&](test::stream& ts)
|
doTestLoop([&](test::stream& ts)
|
||||||
{
|
{
|
||||||
@@ -1158,6 +1208,24 @@ public:
|
|||||||
throw;
|
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
|
void
|
||||||
@@ -2059,14 +2127,15 @@ public:
|
|||||||
stream<socket_type&>>::value);
|
stream<socket_type&>>::value);
|
||||||
|
|
||||||
log << "sizeof(websocket::stream) == " <<
|
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;
|
permessage_deflate pmd;
|
||||||
pmd.client_enable = false;
|
pmd.client_enable = false;
|
||||||
pmd.server_enable = false;
|
pmd.server_enable = false;
|
||||||
|
|
||||||
testOptions();
|
testOptions();
|
||||||
testAccept();
|
|
||||||
testHandshake();
|
testHandshake();
|
||||||
testBadHandshakes();
|
testBadHandshakes();
|
||||||
testBadResponses();
|
testBadResponses();
|
||||||
|
Reference in New Issue
Block a user