mirror of
https://github.com/boostorg/beast.git
synced 2025-07-30 12:57:31 +02:00
permessage-deflate is a compile-time feature (API Change):
fix #849 This adds an additional `bool` template parameter to `websocket::stream`: * When deflateSupported is `true`, the stream will be capable of negotiating the permessage-deflate websocket extension per the configured run-time settings. * When deflateSupported is `false`, the stream will never negotiate the permessage-deflate websocket extension. Furthermore, all of the code necessary for implementing the permessage-deflate extension will be excluded from function instantiations. The resulting emitted object code should be smaller.
This commit is contained in:
@ -1,3 +1,5 @@
|
|||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
Version 151:
|
Version 151:
|
||||||
|
|
||||||
* Sanitizer failures are errors
|
* Sanitizer failures are errors
|
||||||
@ -13,6 +15,7 @@ WebSocket:
|
|||||||
API Changes:
|
API Changes:
|
||||||
|
|
||||||
* http::parser is not MoveConstructible
|
* http::parser is not MoveConstructible
|
||||||
|
* permessage-deflate is a compile-time feature
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -10,13 +10,27 @@
|
|||||||
[section Creating Streams]
|
[section Creating Streams]
|
||||||
|
|
||||||
The interface to the WebSocket implementation is a single template class
|
The interface to the WebSocket implementation is a single template class
|
||||||
[link beast.ref.boost__beast__websocket__stream `stream`]
|
[link beast.ref.boost__beast__websocket__stream `stream`]:
|
||||||
which wraps an existing network transport object or other type of
|
|
||||||
octet oriented stream. The wrapped object is called the "next layer"
|
[ws_snippet_26]
|
||||||
and must meet the requirements of __SyncStream__ if synchronous
|
|
||||||
operations are performed, __AsyncStream__ if asynchronous operations
|
An instance of the stream wraps an existing network transport object
|
||||||
are performed, or both. Any arguments supplied during construction of
|
or other type of octet oriented stream. The wrapped object is called
|
||||||
the stream wrapper are passed to next layer's constructor.
|
the "next layer" and must meet the requirements of __SyncStream__ if
|
||||||
|
synchronous operations are performed, __AsyncStream__ if asynchronous
|
||||||
|
operations are performed, or both. Any arguments supplied during
|
||||||
|
construction of the stream wrapper are passed to next layer's constructor.
|
||||||
|
|
||||||
|
The value of `deflateSupported` determines if the stream will support
|
||||||
|
(but not require) the permessage-deflate extension
|
||||||
|
([@https://tools.ietf.org/html/rfc7692 rfc7692])
|
||||||
|
negotiation during handshaking. This extension allows messages to be
|
||||||
|
optionally automatically compressed using the deflate algorithm prior
|
||||||
|
to transmission. When this boolean value is `false`, the extension is
|
||||||
|
disabled. Applications which do not intend to use the permessage-deflate
|
||||||
|
extension may set the value to `false` to enjoy a reduction in the size
|
||||||
|
of the compiled output, as the necessary compression code (included with
|
||||||
|
Beast) will not be compiled in.
|
||||||
|
|
||||||
Here we declare a websocket stream over a TCP/IP socket with ownership
|
Here we declare a websocket stream over a TCP/IP socket with ownership
|
||||||
of the socket. The `io_context` argument is forwarded to the wrapped
|
of the socket. The `io_context` argument is forwarded to the wrapped
|
||||||
|
@ -75,7 +75,7 @@ native_to_little_uint32(std::uint32_t v, void* buf)
|
|||||||
p[3] = (v >> 24) & 0xff;
|
p[3] = (v >> 24) & 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** WebSocket frame header opcodes. */
|
// frame header opcodes
|
||||||
enum class opcode : std::uint8_t
|
enum class opcode : std::uint8_t
|
||||||
{
|
{
|
||||||
cont = 0,
|
cont = 0,
|
||||||
@ -110,8 +110,7 @@ struct frame_header
|
|||||||
};
|
};
|
||||||
|
|
||||||
// holds the largest possible frame header
|
// holds the largest possible frame header
|
||||||
using fh_buffer =
|
using fh_buffer = flat_static_buffer<14>;
|
||||||
flat_static_buffer<14>;
|
|
||||||
|
|
||||||
// holds the largest possible control frame
|
// holds the largest possible control frame
|
||||||
using frame_buffer =
|
using frame_buffer =
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include <boost/beast/http/rfc7230.hpp>
|
#include <boost/beast/http/rfc7230.hpp>
|
||||||
#include <boost/asio/buffer.hpp>
|
#include <boost/asio/buffer.hpp>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
namespace boost {
|
namespace boost {
|
||||||
namespace beast {
|
namespace beast {
|
||||||
@ -355,85 +356,6 @@ pmd_normalize(pmd_offer& offer)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------
|
|
||||||
|
|
||||||
// Compress a buffer sequence
|
|
||||||
// Returns: `true` if more calls are needed
|
|
||||||
//
|
|
||||||
template<class DeflateStream, class ConstBufferSequence>
|
|
||||||
bool
|
|
||||||
deflate(
|
|
||||||
DeflateStream& zo,
|
|
||||||
boost::asio::mutable_buffer& out,
|
|
||||||
buffers_suffix<ConstBufferSequence>& cb,
|
|
||||||
bool fin,
|
|
||||||
std::size_t& total_in,
|
|
||||||
error_code& ec)
|
|
||||||
{
|
|
||||||
using boost::asio::buffer;
|
|
||||||
BOOST_ASSERT(out.size() >= 6);
|
|
||||||
zlib::z_params zs;
|
|
||||||
zs.avail_in = 0;
|
|
||||||
zs.next_in = nullptr;
|
|
||||||
zs.avail_out = out.size();
|
|
||||||
zs.next_out = out.data();
|
|
||||||
for(auto in : beast::detail::buffers_range(cb))
|
|
||||||
{
|
|
||||||
zs.avail_in = in.size();
|
|
||||||
if(zs.avail_in == 0)
|
|
||||||
continue;
|
|
||||||
zs.next_in = in.data();
|
|
||||||
zo.write(zs, zlib::Flush::none, ec);
|
|
||||||
if(ec)
|
|
||||||
{
|
|
||||||
if(ec != zlib::error::need_buffers)
|
|
||||||
return false;
|
|
||||||
BOOST_ASSERT(zs.avail_out == 0);
|
|
||||||
BOOST_ASSERT(zs.total_out == out.size());
|
|
||||||
ec.assign(0, ec.category());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(zs.avail_out == 0)
|
|
||||||
{
|
|
||||||
BOOST_ASSERT(zs.total_out == out.size());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
BOOST_ASSERT(zs.avail_in == 0);
|
|
||||||
}
|
|
||||||
total_in = zs.total_in;
|
|
||||||
cb.consume(zs.total_in);
|
|
||||||
if(zs.avail_out > 0 && fin)
|
|
||||||
{
|
|
||||||
auto const remain = boost::asio::buffer_size(cb);
|
|
||||||
if(remain == 0)
|
|
||||||
{
|
|
||||||
// Inspired by Mark Adler
|
|
||||||
// https://github.com/madler/zlib/issues/149
|
|
||||||
//
|
|
||||||
// VFALCO We could do this flush twice depending
|
|
||||||
// on how much space is in the output.
|
|
||||||
zo.write(zs, zlib::Flush::block, ec);
|
|
||||||
BOOST_ASSERT(! ec || ec == zlib::error::need_buffers);
|
|
||||||
if(ec == zlib::error::need_buffers)
|
|
||||||
ec.assign(0, ec.category());
|
|
||||||
if(ec)
|
|
||||||
return false;
|
|
||||||
if(zs.avail_out >= 6)
|
|
||||||
{
|
|
||||||
zo.write(zs, zlib::Flush::full, ec);
|
|
||||||
BOOST_ASSERT(! ec);
|
|
||||||
// remove flush marker
|
|
||||||
zs.total_out -= 4;
|
|
||||||
out = buffer(out.data(), zs.total_out);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ec.assign(0, ec.category());
|
|
||||||
out = buffer(out.data(), zs.total_out);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // detail
|
} // detail
|
||||||
} // websocket
|
} // websocket
|
||||||
} // beast
|
} // beast
|
||||||
|
141
include/boost/beast/websocket/detail/stream_base.hpp
Normal file
141
include/boost/beast/websocket/detail/stream_base.hpp
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
// Official repository: https://github.com/boostorg/beast
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef BOOST_BEAST_WEBSOCKET_STREAM_BASE_HPP
|
||||||
|
#define BOOST_BEAST_WEBSOCKET_STREAM_BASE_HPP
|
||||||
|
|
||||||
|
#include <boost/beast/websocket/option.hpp>
|
||||||
|
#include <boost/beast/websocket/detail/pmd_extension.hpp>
|
||||||
|
#include <boost/beast/zlib/deflate_stream.hpp>
|
||||||
|
#include <boost/beast/zlib/inflate_stream.hpp>
|
||||||
|
#include <boost/beast/core/buffers_suffix.hpp>
|
||||||
|
#include <boost/beast/core/error.hpp>
|
||||||
|
#include <boost/asio/buffer.hpp>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
namespace beast {
|
||||||
|
namespace websocket {
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template<bool deflateSupported>
|
||||||
|
struct stream_base
|
||||||
|
{
|
||||||
|
// State information for the permessage-deflate extension
|
||||||
|
struct pmd_type
|
||||||
|
{
|
||||||
|
// `true` if current read message is compressed
|
||||||
|
bool rd_set = false;
|
||||||
|
|
||||||
|
zlib::deflate_stream zo;
|
||||||
|
zlib::inflate_stream zi;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::unique_ptr<pmd_type> pmd_; // pmd settings or nullptr
|
||||||
|
permessage_deflate pmd_opts_; // local pmd options
|
||||||
|
detail::pmd_offer pmd_config_; // offer (client) or negotiation (server)
|
||||||
|
|
||||||
|
// return `true` if current message is deflated
|
||||||
|
bool
|
||||||
|
rd_deflated() const
|
||||||
|
{
|
||||||
|
return pmd_ && pmd_->rd_set;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set whether current message is deflated
|
||||||
|
// returns `false` on protocol violation
|
||||||
|
bool
|
||||||
|
rd_deflated(bool rsv1)
|
||||||
|
{
|
||||||
|
if(pmd_)
|
||||||
|
{
|
||||||
|
pmd_->rd_set = rsv1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return ! rsv1; // pmd not negotiated
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class ConstBufferSequence>
|
||||||
|
bool
|
||||||
|
deflate(
|
||||||
|
boost::asio::mutable_buffer& out,
|
||||||
|
buffers_suffix<ConstBufferSequence>& cb,
|
||||||
|
bool fin,
|
||||||
|
std::size_t& total_in,
|
||||||
|
error_code& ec);
|
||||||
|
|
||||||
|
void
|
||||||
|
do_context_takeover_write(role_type role);
|
||||||
|
|
||||||
|
void
|
||||||
|
inflate(
|
||||||
|
zlib::z_params& zs,
|
||||||
|
zlib::Flush flush,
|
||||||
|
error_code& ec);
|
||||||
|
|
||||||
|
void
|
||||||
|
do_context_takeover_read(role_type role);
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct stream_base<false>
|
||||||
|
{
|
||||||
|
// These stubs are for avoiding linking in the zlib
|
||||||
|
// code when permessage-deflate is not enabled.
|
||||||
|
|
||||||
|
bool
|
||||||
|
rd_deflated() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
rd_deflated(bool rsv1)
|
||||||
|
{
|
||||||
|
return ! rsv1;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class ConstBufferSequence>
|
||||||
|
bool
|
||||||
|
deflate(
|
||||||
|
boost::asio::mutable_buffer&,
|
||||||
|
buffers_suffix<ConstBufferSequence>&,
|
||||||
|
bool,
|
||||||
|
std::size_t&,
|
||||||
|
error_code&)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
do_context_takeover_write(role_type)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
inflate(
|
||||||
|
zlib::z_params&,
|
||||||
|
zlib::Flush,
|
||||||
|
error_code&)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
do_context_takeover_read(role_type)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // detail
|
||||||
|
} // websocket
|
||||||
|
} // beast
|
||||||
|
} // boost
|
||||||
|
|
||||||
|
#endif
|
@ -19,12 +19,12 @@ namespace websocket {
|
|||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
template<class F>
|
template<class F>
|
||||||
using is_RequestDecorator =
|
using is_request_decorator =
|
||||||
typename beast::detail::is_invocable<F,
|
typename beast::detail::is_invocable<F,
|
||||||
void(request_type&)>::type;
|
void(request_type&)>::type;
|
||||||
|
|
||||||
template<class F>
|
template<class F>
|
||||||
using is_ResponseDecorator =
|
using is_response_decorator =
|
||||||
typename beast::detail::is_invocable<F,
|
typename beast::detail::is_invocable<F,
|
||||||
void(response_type&)>::type;
|
void(response_type&)>::type;
|
||||||
|
|
||||||
|
@ -34,20 +34,23 @@ namespace beast {
|
|||||||
namespace websocket {
|
namespace websocket {
|
||||||
|
|
||||||
// Respond to an upgrade HTTP request
|
// Respond to an upgrade HTTP request
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class Handler>
|
template<class Handler>
|
||||||
class stream<NextLayer>::response_op
|
class stream<NextLayer, deflateSupported>::response_op
|
||||||
: public boost::asio::coroutine
|
: public boost::asio::coroutine
|
||||||
{
|
{
|
||||||
struct data
|
struct data
|
||||||
{
|
{
|
||||||
stream<NextLayer>& ws;
|
stream<NextLayer, deflateSupported>& ws;
|
||||||
response_type res;
|
response_type res;
|
||||||
|
|
||||||
template<class Body, class Allocator, class Decorator>
|
template<class Body, class Allocator, class Decorator>
|
||||||
data(Handler const&, stream<NextLayer>& ws_, http::request<
|
data(
|
||||||
Body, http::basic_fields<Allocator>> const& req,
|
Handler const&,
|
||||||
Decorator const& decorator)
|
stream<NextLayer, deflateSupported>& ws_,
|
||||||
|
http::request<Body,
|
||||||
|
http::basic_fields<Allocator>> const& req,
|
||||||
|
Decorator const& decorator)
|
||||||
: ws(ws_)
|
: ws(ws_)
|
||||||
, res(ws_.build_response(req, decorator))
|
, res(ws_.build_response(req, decorator))
|
||||||
{
|
{
|
||||||
@ -62,7 +65,7 @@ public:
|
|||||||
|
|
||||||
template<class DeducedHandler, class... Args>
|
template<class DeducedHandler, class... Args>
|
||||||
response_op(DeducedHandler&& h,
|
response_op(DeducedHandler&& h,
|
||||||
stream<NextLayer>& ws, Args&&... args)
|
stream<NextLayer, deflateSupported>& ws, Args&&... args)
|
||||||
: d_(std::forward<DeducedHandler>(h),
|
: d_(std::forward<DeducedHandler>(h),
|
||||||
ws, std::forward<Args>(args)...)
|
ws, std::forward<Args>(args)...)
|
||||||
{
|
{
|
||||||
@ -78,7 +81,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
using executor_type = boost::asio::associated_executor_t<
|
using executor_type = boost::asio::associated_executor_t<
|
||||||
Handler, decltype(std::declval<stream<NextLayer>&>().get_executor())>;
|
Handler, decltype(std::declval<
|
||||||
|
stream<NextLayer, deflateSupported>&>().get_executor())>;
|
||||||
|
|
||||||
executor_type
|
executor_type
|
||||||
get_executor() const noexcept
|
get_executor() const noexcept
|
||||||
@ -100,10 +104,10 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class Handler>
|
template<class Handler>
|
||||||
void
|
void
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
response_op<Handler>::
|
response_op<Handler>::
|
||||||
operator()(
|
operator()(
|
||||||
error_code ec,
|
error_code ec,
|
||||||
@ -121,7 +125,7 @@ operator()(
|
|||||||
ec = error::handshake_failed;
|
ec = error::handshake_failed;
|
||||||
if(! ec)
|
if(! ec)
|
||||||
{
|
{
|
||||||
pmd_read(d.ws.pmd_config_, d.res);
|
d.ws.do_pmd_config(d.res, is_deflate_supported{});
|
||||||
d.ws.open(role_type::server);
|
d.ws.open(role_type::server);
|
||||||
}
|
}
|
||||||
d_.invoke(ec);
|
d_.invoke(ec);
|
||||||
@ -132,18 +136,20 @@ operator()(
|
|||||||
|
|
||||||
// read and respond to an upgrade request
|
// read and respond to an upgrade request
|
||||||
//
|
//
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class Decorator, class Handler>
|
template<class Decorator, class Handler>
|
||||||
class stream<NextLayer>::accept_op
|
class stream<NextLayer, deflateSupported>::accept_op
|
||||||
: public boost::asio::coroutine
|
: public boost::asio::coroutine
|
||||||
{
|
{
|
||||||
struct data
|
struct data
|
||||||
{
|
{
|
||||||
stream<NextLayer>& ws;
|
stream<NextLayer, deflateSupported>& ws;
|
||||||
Decorator decorator;
|
Decorator decorator;
|
||||||
http::request_parser<http::empty_body> p;
|
http::request_parser<http::empty_body> p;
|
||||||
data(Handler const&, stream<NextLayer>& ws_,
|
data(
|
||||||
Decorator const& decorator_)
|
Handler const&,
|
||||||
|
stream<NextLayer, deflateSupported>& ws_,
|
||||||
|
Decorator const& decorator_)
|
||||||
: ws(ws_)
|
: ws(ws_)
|
||||||
, decorator(decorator_)
|
, decorator(decorator_)
|
||||||
{
|
{
|
||||||
@ -158,7 +164,7 @@ public:
|
|||||||
|
|
||||||
template<class DeducedHandler, class... Args>
|
template<class DeducedHandler, class... Args>
|
||||||
accept_op(DeducedHandler&& h,
|
accept_op(DeducedHandler&& h,
|
||||||
stream<NextLayer>& ws, Args&&... args)
|
stream<NextLayer, deflateSupported>& ws, Args&&... args)
|
||||||
: d_(std::forward<DeducedHandler>(h),
|
: d_(std::forward<DeducedHandler>(h),
|
||||||
ws, std::forward<Args>(args)...)
|
ws, std::forward<Args>(args)...)
|
||||||
{
|
{
|
||||||
@ -174,7 +180,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
using executor_type = boost::asio::associated_executor_t<
|
using executor_type = boost::asio::associated_executor_t<
|
||||||
Handler, decltype(std::declval<stream<NextLayer>&>().get_executor())>;
|
Handler, decltype(std::declval<stream<NextLayer, deflateSupported>&>().get_executor())>;
|
||||||
|
|
||||||
executor_type
|
executor_type
|
||||||
get_executor() const noexcept
|
get_executor() const noexcept
|
||||||
@ -199,11 +205,11 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class Decorator, class Handler>
|
template<class Decorator, class Handler>
|
||||||
template<class Buffers>
|
template<class Buffers>
|
||||||
void
|
void
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
accept_op<Decorator, Handler>::
|
accept_op<Decorator, Handler>::
|
||||||
run(Buffers const& buffers)
|
run(Buffers const& buffers)
|
||||||
{
|
{
|
||||||
@ -228,10 +234,10 @@ run(Buffers const& buffers)
|
|||||||
(*this)(ec);
|
(*this)(ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class Decorator, class Handler>
|
template<class Decorator, class Handler>
|
||||||
void
|
void
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
accept_op<Decorator, Handler>::
|
accept_op<Decorator, Handler>::
|
||||||
operator()(error_code ec, std::size_t)
|
operator()(error_code ec, std::size_t)
|
||||||
{
|
{
|
||||||
@ -280,9 +286,9 @@ operator()(error_code ec, std::size_t)
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
void
|
void
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
accept()
|
accept()
|
||||||
{
|
{
|
||||||
static_assert(is_sync_stream<next_layer_type>::value,
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
@ -293,15 +299,15 @@ accept()
|
|||||||
BOOST_THROW_EXCEPTION(system_error{ec});
|
BOOST_THROW_EXCEPTION(system_error{ec});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class ResponseDecorator>
|
template<class ResponseDecorator>
|
||||||
void
|
void
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
accept_ex(ResponseDecorator const& decorator)
|
accept_ex(ResponseDecorator const& decorator)
|
||||||
{
|
{
|
||||||
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(detail::is_ResponseDecorator<
|
static_assert(detail::is_response_decorator<
|
||||||
ResponseDecorator>::value,
|
ResponseDecorator>::value,
|
||||||
"ResponseDecorator requirements not met");
|
"ResponseDecorator requirements not met");
|
||||||
error_code ec;
|
error_code ec;
|
||||||
@ -310,9 +316,9 @@ accept_ex(ResponseDecorator const& decorator)
|
|||||||
BOOST_THROW_EXCEPTION(system_error{ec});
|
BOOST_THROW_EXCEPTION(system_error{ec});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
void
|
void
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
accept(error_code& ec)
|
accept(error_code& ec)
|
||||||
{
|
{
|
||||||
static_assert(is_sync_stream<next_layer_type>::value,
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
@ -321,26 +327,26 @@ accept(error_code& ec)
|
|||||||
do_accept(&default_decorate_res, ec);
|
do_accept(&default_decorate_res, ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class ResponseDecorator>
|
template<class ResponseDecorator>
|
||||||
void
|
void
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
accept_ex(ResponseDecorator const& decorator, error_code& ec)
|
accept_ex(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");
|
||||||
static_assert(detail::is_ResponseDecorator<
|
static_assert(detail::is_response_decorator<
|
||||||
ResponseDecorator>::value,
|
ResponseDecorator>::value,
|
||||||
"ResponseDecorator requirements not met");
|
"ResponseDecorator requirements not met");
|
||||||
reset();
|
reset();
|
||||||
do_accept(decorator, ec);
|
do_accept(decorator, ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class ConstBufferSequence>
|
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, deflateSupported>::
|
||||||
accept(ConstBufferSequence const& buffers)
|
accept(ConstBufferSequence const& buffers)
|
||||||
{
|
{
|
||||||
static_assert(is_sync_stream<next_layer_type>::value,
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
@ -354,13 +360,13 @@ accept(ConstBufferSequence const& buffers)
|
|||||||
BOOST_THROW_EXCEPTION(system_error{ec});
|
BOOST_THROW_EXCEPTION(system_error{ec});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<
|
template<
|
||||||
class ConstBufferSequence,
|
class ConstBufferSequence,
|
||||||
class ResponseDecorator>
|
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, deflateSupported>::
|
||||||
accept_ex(
|
accept_ex(
|
||||||
ConstBufferSequence const& buffers,
|
ConstBufferSequence const& buffers,
|
||||||
ResponseDecorator const &decorator)
|
ResponseDecorator const &decorator)
|
||||||
@ -370,7 +376,7 @@ accept_ex(
|
|||||||
static_assert(boost::asio::is_const_buffer_sequence<
|
static_assert(boost::asio::is_const_buffer_sequence<
|
||||||
ConstBufferSequence>::value,
|
ConstBufferSequence>::value,
|
||||||
"ConstBufferSequence requirements not met");
|
"ConstBufferSequence requirements not met");
|
||||||
static_assert(detail::is_ResponseDecorator<
|
static_assert(detail::is_response_decorator<
|
||||||
ResponseDecorator>::value,
|
ResponseDecorator>::value,
|
||||||
"ResponseDecorator requirements not met");
|
"ResponseDecorator requirements not met");
|
||||||
error_code ec;
|
error_code ec;
|
||||||
@ -379,11 +385,11 @@ accept_ex(
|
|||||||
BOOST_THROW_EXCEPTION(system_error{ec});
|
BOOST_THROW_EXCEPTION(system_error{ec});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class ConstBufferSequence>
|
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, deflateSupported>::
|
||||||
accept(
|
accept(
|
||||||
ConstBufferSequence const& buffers, error_code& ec)
|
ConstBufferSequence const& buffers, error_code& ec)
|
||||||
{
|
{
|
||||||
@ -412,13 +418,13 @@ accept(
|
|||||||
do_accept(&default_decorate_res, ec);
|
do_accept(&default_decorate_res, ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<
|
template<
|
||||||
class ConstBufferSequence,
|
class ConstBufferSequence,
|
||||||
class ResponseDecorator>
|
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, deflateSupported>::
|
||||||
accept_ex(
|
accept_ex(
|
||||||
ConstBufferSequence const& buffers,
|
ConstBufferSequence const& buffers,
|
||||||
ResponseDecorator const& decorator,
|
ResponseDecorator const& decorator,
|
||||||
@ -451,10 +457,10 @@ accept_ex(
|
|||||||
do_accept(decorator, ec);
|
do_accept(decorator, ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class Body, class Allocator>
|
template<class Body, class Allocator>
|
||||||
void
|
void
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
accept(
|
accept(
|
||||||
http::request<Body,
|
http::request<Body,
|
||||||
http::basic_fields<Allocator>> const& req)
|
http::basic_fields<Allocator>> const& req)
|
||||||
@ -467,12 +473,12 @@ accept(
|
|||||||
BOOST_THROW_EXCEPTION(system_error{ec});
|
BOOST_THROW_EXCEPTION(system_error{ec});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<
|
template<
|
||||||
class Body, class Allocator,
|
class Body, class Allocator,
|
||||||
class ResponseDecorator>
|
class ResponseDecorator>
|
||||||
void
|
void
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
accept_ex(
|
accept_ex(
|
||||||
http::request<Body,
|
http::request<Body,
|
||||||
http::basic_fields<Allocator>> const& req,
|
http::basic_fields<Allocator>> const& req,
|
||||||
@ -480,7 +486,7 @@ accept_ex(
|
|||||||
{
|
{
|
||||||
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(detail::is_ResponseDecorator<
|
static_assert(detail::is_response_decorator<
|
||||||
ResponseDecorator>::value,
|
ResponseDecorator>::value,
|
||||||
"ResponseDecorator requirements not met");
|
"ResponseDecorator requirements not met");
|
||||||
error_code ec;
|
error_code ec;
|
||||||
@ -489,10 +495,10 @@ accept_ex(
|
|||||||
BOOST_THROW_EXCEPTION(system_error{ec});
|
BOOST_THROW_EXCEPTION(system_error{ec});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class Body, class Allocator>
|
template<class Body, class Allocator>
|
||||||
void
|
void
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
accept(
|
accept(
|
||||||
http::request<Body,
|
http::request<Body,
|
||||||
http::basic_fields<Allocator>> const& req,
|
http::basic_fields<Allocator>> const& req,
|
||||||
@ -504,12 +510,12 @@ accept(
|
|||||||
do_accept(req, &default_decorate_res, ec);
|
do_accept(req, &default_decorate_res, ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<
|
template<
|
||||||
class Body, class Allocator,
|
class Body, class Allocator,
|
||||||
class ResponseDecorator>
|
class ResponseDecorator>
|
||||||
void
|
void
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
accept_ex(
|
accept_ex(
|
||||||
http::request<Body,
|
http::request<Body,
|
||||||
http::basic_fields<Allocator>> const& req,
|
http::basic_fields<Allocator>> const& req,
|
||||||
@ -518,7 +524,7 @@ accept_ex(
|
|||||||
{
|
{
|
||||||
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(detail::is_ResponseDecorator<
|
static_assert(detail::is_response_decorator<
|
||||||
ResponseDecorator>::value,
|
ResponseDecorator>::value,
|
||||||
"ResponseDecorator requirements not met");
|
"ResponseDecorator requirements not met");
|
||||||
reset();
|
reset();
|
||||||
@ -527,12 +533,12 @@ accept_ex(
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<
|
template<
|
||||||
class AcceptHandler>
|
class AcceptHandler>
|
||||||
BOOST_ASIO_INITFN_RESULT_TYPE(
|
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||||
AcceptHandler, void(error_code))
|
AcceptHandler, void(error_code))
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
async_accept(
|
async_accept(
|
||||||
AcceptHandler&& handler)
|
AcceptHandler&& handler)
|
||||||
{
|
{
|
||||||
@ -551,20 +557,20 @@ async_accept(
|
|||||||
return init.result.get();
|
return init.result.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<
|
template<
|
||||||
class ResponseDecorator,
|
class ResponseDecorator,
|
||||||
class AcceptHandler>
|
class AcceptHandler>
|
||||||
BOOST_ASIO_INITFN_RESULT_TYPE(
|
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||||
AcceptHandler, void(error_code))
|
AcceptHandler, void(error_code))
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
async_accept_ex(
|
async_accept_ex(
|
||||||
ResponseDecorator const& decorator,
|
ResponseDecorator const& decorator,
|
||||||
AcceptHandler&& handler)
|
AcceptHandler&& handler)
|
||||||
{
|
{
|
||||||
static_assert(is_async_stream<next_layer_type>::value,
|
static_assert(is_async_stream<next_layer_type>::value,
|
||||||
"AsyncStream requirements not met");
|
"AsyncStream requirements not met");
|
||||||
static_assert(detail::is_ResponseDecorator<
|
static_assert(detail::is_response_decorator<
|
||||||
ResponseDecorator>::value,
|
ResponseDecorator>::value,
|
||||||
"ResponseDecorator requirements not met");
|
"ResponseDecorator requirements not met");
|
||||||
boost::asio::async_completion<AcceptHandler,
|
boost::asio::async_completion<AcceptHandler,
|
||||||
@ -580,7 +586,7 @@ async_accept_ex(
|
|||||||
return init.result.get();
|
return init.result.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<
|
template<
|
||||||
class ConstBufferSequence,
|
class ConstBufferSequence,
|
||||||
class AcceptHandler>
|
class AcceptHandler>
|
||||||
@ -588,7 +594,7 @@ typename std::enable_if<
|
|||||||
! http::detail::is_header<ConstBufferSequence>::value,
|
! http::detail::is_header<ConstBufferSequence>::value,
|
||||||
BOOST_ASIO_INITFN_RESULT_TYPE(
|
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||||
AcceptHandler, void(error_code))>::type
|
AcceptHandler, void(error_code))>::type
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
async_accept(
|
async_accept(
|
||||||
ConstBufferSequence const& buffers,
|
ConstBufferSequence const& buffers,
|
||||||
AcceptHandler&& handler)
|
AcceptHandler&& handler)
|
||||||
@ -611,7 +617,7 @@ async_accept(
|
|||||||
return init.result.get();
|
return init.result.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<
|
template<
|
||||||
class ConstBufferSequence,
|
class ConstBufferSequence,
|
||||||
class ResponseDecorator,
|
class ResponseDecorator,
|
||||||
@ -620,7 +626,7 @@ typename std::enable_if<
|
|||||||
! http::detail::is_header<ConstBufferSequence>::value,
|
! http::detail::is_header<ConstBufferSequence>::value,
|
||||||
BOOST_ASIO_INITFN_RESULT_TYPE(
|
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||||
AcceptHandler, void(error_code))>::type
|
AcceptHandler, void(error_code))>::type
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
async_accept_ex(
|
async_accept_ex(
|
||||||
ConstBufferSequence const& buffers,
|
ConstBufferSequence const& buffers,
|
||||||
ResponseDecorator const& decorator,
|
ResponseDecorator const& decorator,
|
||||||
@ -631,7 +637,7 @@ async_accept_ex(
|
|||||||
static_assert(boost::asio::is_const_buffer_sequence<
|
static_assert(boost::asio::is_const_buffer_sequence<
|
||||||
ConstBufferSequence>::value,
|
ConstBufferSequence>::value,
|
||||||
"ConstBufferSequence requirements not met");
|
"ConstBufferSequence requirements not met");
|
||||||
static_assert(detail::is_ResponseDecorator<
|
static_assert(detail::is_response_decorator<
|
||||||
ResponseDecorator>::value,
|
ResponseDecorator>::value,
|
||||||
"ResponseDecorator requirements not met");
|
"ResponseDecorator requirements not met");
|
||||||
boost::asio::async_completion<AcceptHandler,
|
boost::asio::async_completion<AcceptHandler,
|
||||||
@ -647,13 +653,13 @@ async_accept_ex(
|
|||||||
return init.result.get();
|
return init.result.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<
|
template<
|
||||||
class Body, class Allocator,
|
class Body, class Allocator,
|
||||||
class AcceptHandler>
|
class AcceptHandler>
|
||||||
BOOST_ASIO_INITFN_RESULT_TYPE(
|
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||||
AcceptHandler, void(error_code))
|
AcceptHandler, void(error_code))
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
async_accept(
|
async_accept(
|
||||||
http::request<Body, http::basic_fields<Allocator>> const& req,
|
http::request<Body, http::basic_fields<Allocator>> const& req,
|
||||||
AcceptHandler&& handler)
|
AcceptHandler&& handler)
|
||||||
@ -674,14 +680,14 @@ async_accept(
|
|||||||
return init.result.get();
|
return init.result.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<
|
template<
|
||||||
class Body, class Allocator,
|
class Body, class Allocator,
|
||||||
class ResponseDecorator,
|
class ResponseDecorator,
|
||||||
class AcceptHandler>
|
class AcceptHandler>
|
||||||
BOOST_ASIO_INITFN_RESULT_TYPE(
|
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||||
AcceptHandler, void(error_code))
|
AcceptHandler, void(error_code))
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
async_accept_ex(
|
async_accept_ex(
|
||||||
http::request<Body, http::basic_fields<Allocator>> const& req,
|
http::request<Body, http::basic_fields<Allocator>> const& req,
|
||||||
ResponseDecorator const& decorator,
|
ResponseDecorator const& decorator,
|
||||||
@ -689,7 +695,7 @@ async_accept_ex(
|
|||||||
{
|
{
|
||||||
static_assert(is_async_stream<next_layer_type>::value,
|
static_assert(is_async_stream<next_layer_type>::value,
|
||||||
"AsyncStream requirements not met");
|
"AsyncStream requirements not met");
|
||||||
static_assert(detail::is_ResponseDecorator<
|
static_assert(detail::is_response_decorator<
|
||||||
ResponseDecorator>::value,
|
ResponseDecorator>::value,
|
||||||
"ResponseDecorator requirements not met");
|
"ResponseDecorator requirements not met");
|
||||||
boost::asio::async_completion<AcceptHandler,
|
boost::asio::async_completion<AcceptHandler,
|
||||||
@ -708,10 +714,10 @@ async_accept_ex(
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class Decorator>
|
template<class Decorator>
|
||||||
void
|
void
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
do_accept(
|
do_accept(
|
||||||
Decorator const& decorator,
|
Decorator const& decorator,
|
||||||
error_code& ec)
|
error_code& ec)
|
||||||
@ -725,13 +731,14 @@ do_accept(
|
|||||||
do_accept(p.get(), decorator, ec);
|
do_accept(p.get(), decorator, ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class Body, class Allocator,
|
template<class Body, class Allocator,
|
||||||
class Decorator>
|
class Decorator>
|
||||||
void
|
void
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
do_accept(
|
do_accept(
|
||||||
http::request<Body,http::basic_fields<Allocator>> const& req,
|
http::request<Body,
|
||||||
|
http::basic_fields<Allocator>> const& req,
|
||||||
Decorator const& decorator,
|
Decorator const& decorator,
|
||||||
error_code& ec)
|
error_code& ec)
|
||||||
{
|
{
|
||||||
@ -746,7 +753,7 @@ do_accept(
|
|||||||
// teardown if Connection: close.
|
// teardown if Connection: close.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pmd_read(pmd_config_, res);
|
do_pmd_config(res, is_deflate_supported{});
|
||||||
open(role_type::server);
|
open(role_type::server);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,14 +34,14 @@ namespace websocket {
|
|||||||
frame. Finally it invokes the teardown operation to shut down the
|
frame. Finally it invokes the teardown operation to shut down the
|
||||||
underlying connection.
|
underlying connection.
|
||||||
*/
|
*/
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class Handler>
|
template<class Handler>
|
||||||
class stream<NextLayer>::close_op
|
class stream<NextLayer, deflateSupported>::close_op
|
||||||
: public boost::asio::coroutine
|
: public boost::asio::coroutine
|
||||||
{
|
{
|
||||||
struct state
|
struct state
|
||||||
{
|
{
|
||||||
stream<NextLayer>& ws;
|
stream<NextLayer, deflateSupported>& ws;
|
||||||
detail::frame_buffer fb;
|
detail::frame_buffer fb;
|
||||||
error_code ev;
|
error_code ev;
|
||||||
token tok;
|
token tok;
|
||||||
@ -49,7 +49,7 @@ class stream<NextLayer>::close_op
|
|||||||
|
|
||||||
state(
|
state(
|
||||||
Handler const&,
|
Handler const&,
|
||||||
stream<NextLayer>& ws_,
|
stream<NextLayer, deflateSupported>& ws_,
|
||||||
close_reason const& cr)
|
close_reason const& cr)
|
||||||
: ws(ws_)
|
: ws(ws_)
|
||||||
, tok(ws.tok_.unique())
|
, tok(ws.tok_.unique())
|
||||||
@ -69,7 +69,7 @@ public:
|
|||||||
template<class DeducedHandler>
|
template<class DeducedHandler>
|
||||||
close_op(
|
close_op(
|
||||||
DeducedHandler&& h,
|
DeducedHandler&& h,
|
||||||
stream<NextLayer>& ws,
|
stream<NextLayer, deflateSupported>& ws,
|
||||||
close_reason const& cr)
|
close_reason const& cr)
|
||||||
: d_(std::forward<DeducedHandler>(h), ws, cr)
|
: d_(std::forward<DeducedHandler>(h), ws, cr)
|
||||||
{
|
{
|
||||||
@ -85,7 +85,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
using executor_type = boost::asio::associated_executor_t<
|
using executor_type = boost::asio::associated_executor_t<
|
||||||
Handler, decltype(std::declval<stream<NextLayer>&>().get_executor())>;
|
Handler, decltype(std::declval<stream<NextLayer, deflateSupported>&>().get_executor())>;
|
||||||
|
|
||||||
executor_type
|
executor_type
|
||||||
get_executor() const noexcept
|
get_executor() const noexcept
|
||||||
@ -109,10 +109,10 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class Handler>
|
template<class Handler>
|
||||||
void
|
void
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
close_op<Handler>::
|
close_op<Handler>::
|
||||||
operator()(
|
operator()(
|
||||||
error_code ec,
|
error_code ec,
|
||||||
@ -327,9 +327,9 @@ operator()(
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
void
|
void
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
close(close_reason const& cr)
|
close(close_reason const& cr)
|
||||||
{
|
{
|
||||||
static_assert(is_sync_stream<next_layer_type>::value,
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
@ -340,9 +340,9 @@ close(close_reason const& cr)
|
|||||||
BOOST_THROW_EXCEPTION(system_error{ec});
|
BOOST_THROW_EXCEPTION(system_error{ec});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
void
|
void
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
close(close_reason const& cr, error_code& ec)
|
close(close_reason const& cr, error_code& ec)
|
||||||
{
|
{
|
||||||
static_assert(is_sync_stream<next_layer_type>::value,
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
@ -434,11 +434,11 @@ close(close_reason const& cr, error_code& ec)
|
|||||||
ec.assign(0, ec.category());
|
ec.assign(0, ec.category());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class CloseHandler>
|
template<class CloseHandler>
|
||||||
BOOST_ASIO_INITFN_RESULT_TYPE(
|
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||||
CloseHandler, void(error_code))
|
CloseHandler, void(error_code))
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
async_close(close_reason const& cr, CloseHandler&& handler)
|
async_close(close_reason const& cr, CloseHandler&& handler)
|
||||||
{
|
{
|
||||||
static_assert(is_async_stream<next_layer_type>::value,
|
static_assert(is_async_stream<next_layer_type>::value,
|
||||||
|
@ -33,25 +33,27 @@ namespace websocket {
|
|||||||
|
|
||||||
// send the upgrade request and process the response
|
// send the upgrade request and process the response
|
||||||
//
|
//
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class Handler>
|
template<class Handler>
|
||||||
class stream<NextLayer>::handshake_op
|
class stream<NextLayer, deflateSupported>::handshake_op
|
||||||
: public boost::asio::coroutine
|
: public boost::asio::coroutine
|
||||||
{
|
{
|
||||||
struct data
|
struct data
|
||||||
{
|
{
|
||||||
stream<NextLayer>& ws;
|
stream<NextLayer, deflateSupported>& ws;
|
||||||
response_type* res_p;
|
response_type* res_p;
|
||||||
detail::sec_ws_key_type key;
|
detail::sec_ws_key_type key;
|
||||||
http::request<http::empty_body> req;
|
http::request<http::empty_body> req;
|
||||||
response_type res;
|
response_type res;
|
||||||
|
|
||||||
template<class Decorator>
|
template<class Decorator>
|
||||||
data(Handler const&, stream<NextLayer>& ws_,
|
data(
|
||||||
|
Handler const&,
|
||||||
|
stream<NextLayer, deflateSupported>& ws_,
|
||||||
response_type* res_p_,
|
response_type* res_p_,
|
||||||
string_view host,
|
string_view host,
|
||||||
string_view target,
|
string_view target,
|
||||||
Decorator const& decorator)
|
Decorator const& decorator)
|
||||||
: ws(ws_)
|
: ws(ws_)
|
||||||
, res_p(res_p_)
|
, res_p(res_p_)
|
||||||
, req(ws.build_request(key,
|
, req(ws.build_request(key,
|
||||||
@ -69,7 +71,7 @@ public:
|
|||||||
|
|
||||||
template<class DeducedHandler, class... Args>
|
template<class DeducedHandler, class... Args>
|
||||||
handshake_op(DeducedHandler&& h,
|
handshake_op(DeducedHandler&& h,
|
||||||
stream<NextLayer>& ws, Args&&... args)
|
stream<NextLayer, deflateSupported>& ws, Args&&... args)
|
||||||
: d_(std::forward<DeducedHandler>(h),
|
: d_(std::forward<DeducedHandler>(h),
|
||||||
ws, std::forward<Args>(args)...)
|
ws, std::forward<Args>(args)...)
|
||||||
{
|
{
|
||||||
@ -85,7 +87,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
using executor_type = boost::asio::associated_executor_t<
|
using executor_type = boost::asio::associated_executor_t<
|
||||||
Handler, decltype(std::declval<stream<NextLayer>&>().get_executor())>;
|
Handler, decltype(std::declval<stream<NextLayer, deflateSupported>&>().get_executor())>;
|
||||||
|
|
||||||
executor_type
|
executor_type
|
||||||
get_executor() const noexcept
|
get_executor() const noexcept
|
||||||
@ -108,17 +110,18 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class Handler>
|
template<class Handler>
|
||||||
void
|
void
|
||||||
stream<NextLayer>::handshake_op<Handler>::
|
stream<NextLayer, deflateSupported>::
|
||||||
|
handshake_op<Handler>::
|
||||||
operator()(error_code ec, std::size_t)
|
operator()(error_code ec, std::size_t)
|
||||||
{
|
{
|
||||||
auto& d = *d_;
|
auto& d = *d_;
|
||||||
BOOST_ASIO_CORO_REENTER(*this)
|
BOOST_ASIO_CORO_REENTER(*this)
|
||||||
{
|
{
|
||||||
// Send HTTP Upgrade
|
// Send HTTP Upgrade
|
||||||
pmd_read(d.ws.pmd_config_, d.req);
|
d.ws.do_pmd_config(d.req, is_deflate_supported{});
|
||||||
BOOST_ASIO_CORO_YIELD
|
BOOST_ASIO_CORO_YIELD
|
||||||
http::async_write(d.ws.stream_,
|
http::async_write(d.ws.stream_,
|
||||||
d.req, std::move(*this));
|
d.req, std::move(*this));
|
||||||
@ -146,11 +149,11 @@ operator()(error_code ec, std::size_t)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class HandshakeHandler>
|
template<class HandshakeHandler>
|
||||||
BOOST_ASIO_INITFN_RESULT_TYPE(
|
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||||
HandshakeHandler, void(error_code))
|
HandshakeHandler, void(error_code))
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
async_handshake(string_view host,
|
async_handshake(string_view host,
|
||||||
string_view target,
|
string_view target,
|
||||||
HandshakeHandler&& handler)
|
HandshakeHandler&& handler)
|
||||||
@ -166,11 +169,11 @@ async_handshake(string_view host,
|
|||||||
return init.result.get();
|
return init.result.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class HandshakeHandler>
|
template<class HandshakeHandler>
|
||||||
BOOST_ASIO_INITFN_RESULT_TYPE(
|
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||||
HandshakeHandler, void(error_code))
|
HandshakeHandler, void(error_code))
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
async_handshake(response_type& res,
|
async_handshake(response_type& res,
|
||||||
string_view host,
|
string_view host,
|
||||||
string_view target,
|
string_view target,
|
||||||
@ -187,11 +190,11 @@ async_handshake(response_type& res,
|
|||||||
return init.result.get();
|
return init.result.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class RequestDecorator, class HandshakeHandler>
|
template<class RequestDecorator, class HandshakeHandler>
|
||||||
BOOST_ASIO_INITFN_RESULT_TYPE(
|
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||||
HandshakeHandler, void(error_code))
|
HandshakeHandler, void(error_code))
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
async_handshake_ex(string_view host,
|
async_handshake_ex(string_view host,
|
||||||
string_view target,
|
string_view target,
|
||||||
RequestDecorator const& decorator,
|
RequestDecorator const& decorator,
|
||||||
@ -199,7 +202,7 @@ async_handshake_ex(string_view host,
|
|||||||
{
|
{
|
||||||
static_assert(is_async_stream<next_layer_type>::value,
|
static_assert(is_async_stream<next_layer_type>::value,
|
||||||
"AsyncStream requirements not met");
|
"AsyncStream requirements not met");
|
||||||
static_assert(detail::is_RequestDecorator<
|
static_assert(detail::is_request_decorator<
|
||||||
RequestDecorator>::value,
|
RequestDecorator>::value,
|
||||||
"RequestDecorator requirements not met");
|
"RequestDecorator requirements not met");
|
||||||
boost::asio::async_completion<HandshakeHandler,
|
boost::asio::async_completion<HandshakeHandler,
|
||||||
@ -211,11 +214,11 @@ async_handshake_ex(string_view host,
|
|||||||
return init.result.get();
|
return init.result.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class RequestDecorator, class HandshakeHandler>
|
template<class RequestDecorator, class HandshakeHandler>
|
||||||
BOOST_ASIO_INITFN_RESULT_TYPE(
|
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||||
HandshakeHandler, void(error_code))
|
HandshakeHandler, void(error_code))
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
async_handshake_ex(response_type& res,
|
async_handshake_ex(response_type& res,
|
||||||
string_view host,
|
string_view host,
|
||||||
string_view target,
|
string_view target,
|
||||||
@ -224,7 +227,7 @@ async_handshake_ex(response_type& res,
|
|||||||
{
|
{
|
||||||
static_assert(is_async_stream<next_layer_type>::value,
|
static_assert(is_async_stream<next_layer_type>::value,
|
||||||
"AsyncStream requirements not met");
|
"AsyncStream requirements not met");
|
||||||
static_assert(detail::is_RequestDecorator<
|
static_assert(detail::is_request_decorator<
|
||||||
RequestDecorator>::value,
|
RequestDecorator>::value,
|
||||||
"RequestDecorator requirements not met");
|
"RequestDecorator requirements not met");
|
||||||
boost::asio::async_completion<HandshakeHandler,
|
boost::asio::async_completion<HandshakeHandler,
|
||||||
@ -236,9 +239,9 @@ async_handshake_ex(response_type& res,
|
|||||||
return init.result.get();
|
return init.result.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
void
|
void
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
handshake(string_view host,
|
handshake(string_view host,
|
||||||
string_view target)
|
string_view target)
|
||||||
{
|
{
|
||||||
@ -251,9 +254,9 @@ handshake(string_view host,
|
|||||||
BOOST_THROW_EXCEPTION(system_error{ec});
|
BOOST_THROW_EXCEPTION(system_error{ec});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
void
|
void
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
handshake(response_type& res,
|
handshake(response_type& res,
|
||||||
string_view host,
|
string_view host,
|
||||||
string_view target)
|
string_view target)
|
||||||
@ -266,17 +269,17 @@ handshake(response_type& res,
|
|||||||
BOOST_THROW_EXCEPTION(system_error{ec});
|
BOOST_THROW_EXCEPTION(system_error{ec});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class RequestDecorator>
|
template<class RequestDecorator>
|
||||||
void
|
void
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
handshake_ex(string_view host,
|
handshake_ex(string_view host,
|
||||||
string_view target,
|
string_view target,
|
||||||
RequestDecorator const& decorator)
|
RequestDecorator const& decorator)
|
||||||
{
|
{
|
||||||
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(detail::is_RequestDecorator<
|
static_assert(detail::is_request_decorator<
|
||||||
RequestDecorator>::value,
|
RequestDecorator>::value,
|
||||||
"RequestDecorator requirements not met");
|
"RequestDecorator requirements not met");
|
||||||
error_code ec;
|
error_code ec;
|
||||||
@ -285,10 +288,10 @@ handshake_ex(string_view host,
|
|||||||
BOOST_THROW_EXCEPTION(system_error{ec});
|
BOOST_THROW_EXCEPTION(system_error{ec});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class RequestDecorator>
|
template<class RequestDecorator>
|
||||||
void
|
void
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
handshake_ex(response_type& res,
|
handshake_ex(response_type& res,
|
||||||
string_view host,
|
string_view host,
|
||||||
string_view target,
|
string_view target,
|
||||||
@ -296,7 +299,7 @@ handshake_ex(response_type& res,
|
|||||||
{
|
{
|
||||||
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(detail::is_RequestDecorator<
|
static_assert(detail::is_request_decorator<
|
||||||
RequestDecorator>::value,
|
RequestDecorator>::value,
|
||||||
"RequestDecorator requirements not met");
|
"RequestDecorator requirements not met");
|
||||||
error_code ec;
|
error_code ec;
|
||||||
@ -305,9 +308,9 @@ handshake_ex(response_type& res,
|
|||||||
BOOST_THROW_EXCEPTION(system_error{ec});
|
BOOST_THROW_EXCEPTION(system_error{ec});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
void
|
void
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
handshake(string_view host,
|
handshake(string_view host,
|
||||||
string_view target, error_code& ec)
|
string_view target, error_code& ec)
|
||||||
{
|
{
|
||||||
@ -317,9 +320,9 @@ handshake(string_view host,
|
|||||||
host, target, &default_decorate_req, ec);
|
host, target, &default_decorate_req, ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
void
|
void
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
handshake(response_type& res,
|
handshake(response_type& res,
|
||||||
string_view host,
|
string_view host,
|
||||||
string_view target,
|
string_view target,
|
||||||
@ -331,10 +334,10 @@ handshake(response_type& res,
|
|||||||
host, target, &default_decorate_req, ec);
|
host, target, &default_decorate_req, ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class RequestDecorator>
|
template<class RequestDecorator>
|
||||||
void
|
void
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
handshake_ex(string_view host,
|
handshake_ex(string_view host,
|
||||||
string_view target,
|
string_view target,
|
||||||
RequestDecorator const& decorator,
|
RequestDecorator const& decorator,
|
||||||
@ -342,17 +345,17 @@ handshake_ex(string_view host,
|
|||||||
{
|
{
|
||||||
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(detail::is_RequestDecorator<
|
static_assert(detail::is_request_decorator<
|
||||||
RequestDecorator>::value,
|
RequestDecorator>::value,
|
||||||
"RequestDecorator requirements not met");
|
"RequestDecorator requirements not met");
|
||||||
do_handshake(nullptr,
|
do_handshake(nullptr,
|
||||||
host, target, decorator, ec);
|
host, target, decorator, ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class RequestDecorator>
|
template<class RequestDecorator>
|
||||||
void
|
void
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
handshake_ex(response_type& res,
|
handshake_ex(response_type& res,
|
||||||
string_view host,
|
string_view host,
|
||||||
string_view target,
|
string_view target,
|
||||||
@ -361,7 +364,7 @@ handshake_ex(response_type& res,
|
|||||||
{
|
{
|
||||||
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(detail::is_RequestDecorator<
|
static_assert(detail::is_request_decorator<
|
||||||
RequestDecorator>::value,
|
RequestDecorator>::value,
|
||||||
"RequestDecorator requirements not met");
|
"RequestDecorator requirements not met");
|
||||||
do_handshake(&res,
|
do_handshake(&res,
|
||||||
@ -370,10 +373,10 @@ handshake_ex(response_type& res,
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class RequestDecorator>
|
template<class RequestDecorator>
|
||||||
void
|
void
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
do_handshake(
|
do_handshake(
|
||||||
response_type* res_p,
|
response_type* res_p,
|
||||||
string_view host,
|
string_view host,
|
||||||
@ -387,7 +390,7 @@ do_handshake(
|
|||||||
{
|
{
|
||||||
auto const req = build_request(
|
auto const req = build_request(
|
||||||
key, host, target, decorator);
|
key, host, target, decorator);
|
||||||
pmd_read(pmd_config_, req);
|
do_pmd_config(req, is_deflate_supported{});
|
||||||
http::write(stream_, req, ec);
|
http::write(stream_, req, ec);
|
||||||
}
|
}
|
||||||
if(ec)
|
if(ec)
|
||||||
|
@ -32,20 +32,20 @@ namespace websocket {
|
|||||||
It only sends the frames it does not make attempts to read
|
It only sends the frames it does not make attempts to read
|
||||||
any frame data.
|
any frame data.
|
||||||
*/
|
*/
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class Handler>
|
template<class Handler>
|
||||||
class stream<NextLayer>::ping_op
|
class stream<NextLayer, deflateSupported>::ping_op
|
||||||
: public boost::asio::coroutine
|
: public boost::asio::coroutine
|
||||||
{
|
{
|
||||||
struct state
|
struct state
|
||||||
{
|
{
|
||||||
stream<NextLayer>& ws;
|
stream<NextLayer, deflateSupported>& ws;
|
||||||
detail::frame_buffer fb;
|
detail::frame_buffer fb;
|
||||||
token tok;
|
token tok;
|
||||||
|
|
||||||
state(
|
state(
|
||||||
Handler const&,
|
Handler const&,
|
||||||
stream<NextLayer>& ws_,
|
stream<NextLayer, deflateSupported>& ws_,
|
||||||
detail::opcode op,
|
detail::opcode op,
|
||||||
ping_data const& payload)
|
ping_data const& payload)
|
||||||
: ws(ws_)
|
: ws(ws_)
|
||||||
@ -67,7 +67,7 @@ public:
|
|||||||
template<class DeducedHandler>
|
template<class DeducedHandler>
|
||||||
ping_op(
|
ping_op(
|
||||||
DeducedHandler&& h,
|
DeducedHandler&& h,
|
||||||
stream<NextLayer>& ws,
|
stream<NextLayer, deflateSupported>& ws,
|
||||||
detail::opcode op,
|
detail::opcode op,
|
||||||
ping_data const& payload)
|
ping_data const& payload)
|
||||||
: d_(std::forward<DeducedHandler>(h),
|
: d_(std::forward<DeducedHandler>(h),
|
||||||
@ -85,7 +85,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
using executor_type = boost::asio::associated_executor_t<
|
using executor_type = boost::asio::associated_executor_t<
|
||||||
Handler, decltype(std::declval<stream<NextLayer>&>().get_executor())>;
|
Handler, decltype(std::declval<stream<NextLayer, deflateSupported>&>().get_executor())>;
|
||||||
|
|
||||||
executor_type
|
executor_type
|
||||||
get_executor() const noexcept
|
get_executor() const noexcept
|
||||||
@ -107,10 +107,10 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class Handler>
|
template<class Handler>
|
||||||
void
|
void
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
ping_op<Handler>::
|
ping_op<Handler>::
|
||||||
operator()(error_code ec, std::size_t)
|
operator()(error_code ec, std::size_t)
|
||||||
{
|
{
|
||||||
@ -174,9 +174,9 @@ operator()(error_code ec, std::size_t)
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
void
|
void
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
ping(ping_data const& payload)
|
ping(ping_data const& payload)
|
||||||
{
|
{
|
||||||
error_code ec;
|
error_code ec;
|
||||||
@ -185,9 +185,9 @@ ping(ping_data const& payload)
|
|||||||
BOOST_THROW_EXCEPTION(system_error{ec});
|
BOOST_THROW_EXCEPTION(system_error{ec});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
void
|
void
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
ping(ping_data const& payload, error_code& ec)
|
ping(ping_data const& payload, error_code& ec)
|
||||||
{
|
{
|
||||||
// Make sure the stream is open
|
// Make sure the stream is open
|
||||||
@ -201,9 +201,9 @@ ping(ping_data const& payload, error_code& ec)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
void
|
void
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
pong(ping_data const& payload)
|
pong(ping_data const& payload)
|
||||||
{
|
{
|
||||||
error_code ec;
|
error_code ec;
|
||||||
@ -212,9 +212,9 @@ pong(ping_data const& payload)
|
|||||||
BOOST_THROW_EXCEPTION(system_error{ec});
|
BOOST_THROW_EXCEPTION(system_error{ec});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
void
|
void
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
pong(ping_data const& payload, error_code& ec)
|
pong(ping_data const& payload, error_code& ec)
|
||||||
{
|
{
|
||||||
// Make sure the stream is open
|
// Make sure the stream is open
|
||||||
@ -228,11 +228,11 @@ pong(ping_data const& payload, error_code& ec)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class WriteHandler>
|
template<class WriteHandler>
|
||||||
BOOST_ASIO_INITFN_RESULT_TYPE(
|
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||||
WriteHandler, void(error_code))
|
WriteHandler, void(error_code))
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
async_ping(ping_data const& payload, WriteHandler&& handler)
|
async_ping(ping_data const& payload, WriteHandler&& handler)
|
||||||
{
|
{
|
||||||
static_assert(is_async_stream<next_layer_type>::value,
|
static_assert(is_async_stream<next_layer_type>::value,
|
||||||
@ -246,11 +246,11 @@ async_ping(ping_data const& payload, WriteHandler&& handler)
|
|||||||
return init.result.get();
|
return init.result.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class WriteHandler>
|
template<class WriteHandler>
|
||||||
BOOST_ASIO_INITFN_RESULT_TYPE(
|
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||||
WriteHandler, void(error_code))
|
WriteHandler, void(error_code))
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
async_pong(ping_data const& payload, WriteHandler&& handler)
|
async_pong(ping_data const& payload, WriteHandler&& handler)
|
||||||
{
|
{
|
||||||
static_assert(is_async_stream<next_layer_type>::value,
|
static_assert(is_async_stream<next_layer_type>::value,
|
||||||
|
@ -35,19 +35,52 @@ namespace boost {
|
|||||||
namespace beast {
|
namespace beast {
|
||||||
namespace websocket {
|
namespace websocket {
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline
|
||||||
|
void
|
||||||
|
stream_base<true>::
|
||||||
|
inflate(
|
||||||
|
zlib::z_params& zs,
|
||||||
|
zlib::Flush flush,
|
||||||
|
error_code& ec)
|
||||||
|
{
|
||||||
|
this->pmd_->zi.write(zs, flush, ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline
|
||||||
|
void
|
||||||
|
stream_base<true>::
|
||||||
|
do_context_takeover_read(role_type role)
|
||||||
|
{
|
||||||
|
if((role == role_type::client &&
|
||||||
|
pmd_config_.server_no_context_takeover) ||
|
||||||
|
(role == role_type::server &&
|
||||||
|
pmd_config_.client_no_context_takeover))
|
||||||
|
{
|
||||||
|
pmd_->zi.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // detail
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
/* Read some message frame data.
|
/* Read some message frame data.
|
||||||
|
|
||||||
Also reads and handles control frames.
|
Also reads and handles control frames.
|
||||||
*/
|
*/
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<
|
template<
|
||||||
class MutableBufferSequence,
|
class MutableBufferSequence,
|
||||||
class Handler>
|
class Handler>
|
||||||
class stream<NextLayer>::read_some_op
|
class stream<NextLayer, deflateSupported>::read_some_op
|
||||||
: public boost::asio::coroutine
|
: public boost::asio::coroutine
|
||||||
{
|
{
|
||||||
Handler h_;
|
Handler h_;
|
||||||
stream<NextLayer>& ws_;
|
stream<NextLayer, deflateSupported>& ws_;
|
||||||
MutableBufferSequence bs_;
|
MutableBufferSequence bs_;
|
||||||
buffers_suffix<MutableBufferSequence> cb_;
|
buffers_suffix<MutableBufferSequence> cb_;
|
||||||
std::size_t bytes_written_ = 0;
|
std::size_t bytes_written_ = 0;
|
||||||
@ -64,7 +97,7 @@ public:
|
|||||||
template<class DeducedHandler>
|
template<class DeducedHandler>
|
||||||
read_some_op(
|
read_some_op(
|
||||||
DeducedHandler&& h,
|
DeducedHandler&& h,
|
||||||
stream<NextLayer>& ws,
|
stream<NextLayer, deflateSupported>& ws,
|
||||||
MutableBufferSequence const& bs)
|
MutableBufferSequence const& bs)
|
||||||
: h_(std::forward<DeducedHandler>(h))
|
: h_(std::forward<DeducedHandler>(h))
|
||||||
, ws_(ws)
|
, ws_(ws)
|
||||||
@ -85,7 +118,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
using executor_type = boost::asio::associated_executor_t<
|
using executor_type = boost::asio::associated_executor_t<
|
||||||
Handler, decltype(std::declval<stream<NextLayer>&>().get_executor())>;
|
Handler, decltype(std::declval<stream<NextLayer, deflateSupported>&>().get_executor())>;
|
||||||
|
|
||||||
executor_type
|
executor_type
|
||||||
get_executor() const noexcept
|
get_executor() const noexcept
|
||||||
@ -114,10 +147,10 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class MutableBufferSequence, class Handler>
|
template<class MutableBufferSequence, class Handler>
|
||||||
void
|
void
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
read_some_op<MutableBufferSequence, Handler>::
|
read_some_op<MutableBufferSequence, Handler>::
|
||||||
operator()(
|
operator()(
|
||||||
error_code ec,
|
error_code ec,
|
||||||
@ -404,7 +437,7 @@ operator()(
|
|||||||
}
|
}
|
||||||
ws_.rd_done_ = false;
|
ws_.rd_done_ = false;
|
||||||
}
|
}
|
||||||
if(! ws_.pmd_ || ! ws_.pmd_->rd_set)
|
if(! ws_.rd_deflated())
|
||||||
{
|
{
|
||||||
if(ws_.rd_remain_ > 0)
|
if(ws_.rd_remain_ > 0)
|
||||||
{
|
{
|
||||||
@ -546,7 +579,7 @@ operator()(
|
|||||||
0x00, 0x00, 0xff, 0xff };
|
0x00, 0x00, 0xff, 0xff };
|
||||||
zs.next_in = empty_block;
|
zs.next_in = empty_block;
|
||||||
zs.avail_in = sizeof(empty_block);
|
zs.avail_in = sizeof(empty_block);
|
||||||
ws_.pmd_->zi.write(zs, zlib::Flush::sync, ec);
|
ws_.inflate(zs, zlib::Flush::sync, ec);
|
||||||
if(! ec)
|
if(! ec)
|
||||||
{
|
{
|
||||||
// https://github.com/madler/zlib/issues/280
|
// https://github.com/madler/zlib/issues/280
|
||||||
@ -555,12 +588,7 @@ operator()(
|
|||||||
}
|
}
|
||||||
if(! ws_.check_ok(ec))
|
if(! ws_.check_ok(ec))
|
||||||
goto upcall;
|
goto upcall;
|
||||||
if(
|
ws_.do_context_takeover_read(ws_.role_);
|
||||||
(ws_.role_ == role_type::client &&
|
|
||||||
ws_.pmd_config_.server_no_context_takeover) ||
|
|
||||||
(ws_.role_ == role_type::server &&
|
|
||||||
ws_.pmd_config_.client_no_context_takeover))
|
|
||||||
ws_.pmd_->zi.reset();
|
|
||||||
ws_.rd_done_ = true;
|
ws_.rd_done_ = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -568,7 +596,7 @@ operator()(
|
|||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ws_.pmd_->zi.write(zs, zlib::Flush::sync, ec);
|
ws_.inflate(zs, zlib::Flush::sync, ec);
|
||||||
if(! ws_.check_ok(ec))
|
if(! ws_.check_ok(ec))
|
||||||
goto upcall;
|
goto upcall;
|
||||||
if(ws_.rd_msg_max_ && beast::detail::sum_exceeds(
|
if(ws_.rd_msg_max_ && beast::detail::sum_exceeds(
|
||||||
@ -699,15 +727,15 @@ operator()(
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<
|
template<
|
||||||
class DynamicBuffer,
|
class DynamicBuffer,
|
||||||
class Handler>
|
class Handler>
|
||||||
class stream<NextLayer>::read_op
|
class stream<NextLayer, deflateSupported>::read_op
|
||||||
: public boost::asio::coroutine
|
: public boost::asio::coroutine
|
||||||
{
|
{
|
||||||
Handler h_;
|
Handler h_;
|
||||||
stream<NextLayer>& ws_;
|
stream<NextLayer, deflateSupported>& ws_;
|
||||||
DynamicBuffer& b_;
|
DynamicBuffer& b_;
|
||||||
std::size_t limit_;
|
std::size_t limit_;
|
||||||
std::size_t bytes_written_ = 0;
|
std::size_t bytes_written_ = 0;
|
||||||
@ -723,7 +751,7 @@ public:
|
|||||||
template<class DeducedHandler>
|
template<class DeducedHandler>
|
||||||
read_op(
|
read_op(
|
||||||
DeducedHandler&& h,
|
DeducedHandler&& h,
|
||||||
stream<NextLayer>& ws,
|
stream<NextLayer, deflateSupported>& ws,
|
||||||
DynamicBuffer& b,
|
DynamicBuffer& b,
|
||||||
std::size_t limit,
|
std::size_t limit,
|
||||||
bool some)
|
bool some)
|
||||||
@ -743,7 +771,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
using executor_type = boost::asio::associated_executor_t<
|
using executor_type = boost::asio::associated_executor_t<
|
||||||
Handler, decltype(std::declval<stream<NextLayer>&>().get_executor())>;
|
Handler, decltype(std::declval<stream<NextLayer, deflateSupported>&>().get_executor())>;
|
||||||
|
|
||||||
executor_type
|
executor_type
|
||||||
get_executor() const noexcept
|
get_executor() const noexcept
|
||||||
@ -765,10 +793,10 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class DynamicBuffer, class Handler>
|
template<class DynamicBuffer, class Handler>
|
||||||
void
|
void
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
read_op<DynamicBuffer, Handler>::
|
read_op<DynamicBuffer, Handler>::
|
||||||
operator()(
|
operator()(
|
||||||
error_code ec,
|
error_code ec,
|
||||||
@ -816,10 +844,10 @@ operator()(
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class DynamicBuffer>
|
template<class DynamicBuffer>
|
||||||
std::size_t
|
std::size_t
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
read(DynamicBuffer& buffer)
|
read(DynamicBuffer& buffer)
|
||||||
{
|
{
|
||||||
static_assert(is_sync_stream<next_layer_type>::value,
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
@ -834,10 +862,10 @@ read(DynamicBuffer& buffer)
|
|||||||
return bytes_written;
|
return bytes_written;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class DynamicBuffer>
|
template<class DynamicBuffer>
|
||||||
std::size_t
|
std::size_t
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
read(DynamicBuffer& buffer, error_code& ec)
|
read(DynamicBuffer& buffer, error_code& ec)
|
||||||
{
|
{
|
||||||
static_assert(is_sync_stream<next_layer_type>::value,
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
@ -856,11 +884,11 @@ read(DynamicBuffer& buffer, error_code& ec)
|
|||||||
return bytes_written;
|
return bytes_written;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class DynamicBuffer, class ReadHandler>
|
template<class DynamicBuffer, class ReadHandler>
|
||||||
BOOST_ASIO_INITFN_RESULT_TYPE(
|
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||||
ReadHandler, void(error_code, std::size_t))
|
ReadHandler, void(error_code, std::size_t))
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
async_read(DynamicBuffer& buffer, ReadHandler&& handler)
|
async_read(DynamicBuffer& buffer, ReadHandler&& handler)
|
||||||
{
|
{
|
||||||
static_assert(is_async_stream<next_layer_type>::value,
|
static_assert(is_async_stream<next_layer_type>::value,
|
||||||
@ -884,10 +912,10 @@ async_read(DynamicBuffer& buffer, ReadHandler&& handler)
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class DynamicBuffer>
|
template<class DynamicBuffer>
|
||||||
std::size_t
|
std::size_t
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
read_some(
|
read_some(
|
||||||
DynamicBuffer& buffer,
|
DynamicBuffer& buffer,
|
||||||
std::size_t limit)
|
std::size_t limit)
|
||||||
@ -905,10 +933,10 @@ read_some(
|
|||||||
return bytes_written;
|
return bytes_written;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class DynamicBuffer>
|
template<class DynamicBuffer>
|
||||||
std::size_t
|
std::size_t
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
read_some(
|
read_some(
|
||||||
DynamicBuffer& buffer,
|
DynamicBuffer& buffer,
|
||||||
std::size_t limit,
|
std::size_t limit,
|
||||||
@ -941,11 +969,11 @@ read_some(
|
|||||||
return bytes_written;
|
return bytes_written;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class DynamicBuffer, class ReadHandler>
|
template<class DynamicBuffer, class ReadHandler>
|
||||||
BOOST_ASIO_INITFN_RESULT_TYPE(
|
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||||
ReadHandler, void(error_code, std::size_t))
|
ReadHandler, void(error_code, std::size_t))
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
async_read_some(
|
async_read_some(
|
||||||
DynamicBuffer& buffer,
|
DynamicBuffer& buffer,
|
||||||
std::size_t limit,
|
std::size_t limit,
|
||||||
@ -972,10 +1000,10 @@ async_read_some(
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class MutableBufferSequence>
|
template<class MutableBufferSequence>
|
||||||
std::size_t
|
std::size_t
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
read_some(
|
read_some(
|
||||||
MutableBufferSequence const& buffers)
|
MutableBufferSequence const& buffers)
|
||||||
{
|
{
|
||||||
@ -991,10 +1019,10 @@ read_some(
|
|||||||
return bytes_written;
|
return bytes_written;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class MutableBufferSequence>
|
template<class MutableBufferSequence>
|
||||||
std::size_t
|
std::size_t
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
read_some(
|
read_some(
|
||||||
MutableBufferSequence const& buffers,
|
MutableBufferSequence const& buffers,
|
||||||
error_code& ec)
|
error_code& ec)
|
||||||
@ -1125,7 +1153,7 @@ loop:
|
|||||||
{
|
{
|
||||||
ec.assign(0, ec.category());
|
ec.assign(0, ec.category());
|
||||||
}
|
}
|
||||||
if(! pmd_ || ! pmd_->rd_set)
|
if(! this->rd_deflated())
|
||||||
{
|
{
|
||||||
if(rd_remain_ > 0)
|
if(rd_remain_ > 0)
|
||||||
{
|
{
|
||||||
@ -1273,7 +1301,7 @@ loop:
|
|||||||
0x00, 0x00, 0xff, 0xff };
|
0x00, 0x00, 0xff, 0xff };
|
||||||
zs.next_in = empty_block;
|
zs.next_in = empty_block;
|
||||||
zs.avail_in = sizeof(empty_block);
|
zs.avail_in = sizeof(empty_block);
|
||||||
pmd_->zi.write(zs, zlib::Flush::sync, ec);
|
this->inflate(zs, zlib::Flush::sync, ec);
|
||||||
if(! ec)
|
if(! ec)
|
||||||
{
|
{
|
||||||
// https://github.com/madler/zlib/issues/280
|
// https://github.com/madler/zlib/issues/280
|
||||||
@ -1282,12 +1310,7 @@ loop:
|
|||||||
}
|
}
|
||||||
if(! check_ok(ec))
|
if(! check_ok(ec))
|
||||||
return bytes_written;
|
return bytes_written;
|
||||||
if(
|
this->do_context_takeover_read(role_);
|
||||||
(role_ == role_type::client &&
|
|
||||||
pmd_config_.server_no_context_takeover) ||
|
|
||||||
(role_ == role_type::server &&
|
|
||||||
pmd_config_.client_no_context_takeover))
|
|
||||||
pmd_->zi.reset();
|
|
||||||
rd_done_ = true;
|
rd_done_ = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1295,7 +1318,7 @@ loop:
|
|||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
pmd_->zi.write(zs, zlib::Flush::sync, ec);
|
this->inflate(zs, zlib::Flush::sync, ec);
|
||||||
if(! check_ok(ec))
|
if(! check_ok(ec))
|
||||||
return bytes_written;
|
return bytes_written;
|
||||||
if(rd_msg_max_ && beast::detail::sum_exceeds(
|
if(rd_msg_max_ && beast::detail::sum_exceeds(
|
||||||
@ -1328,11 +1351,11 @@ loop:
|
|||||||
return bytes_written;
|
return bytes_written;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class MutableBufferSequence, class ReadHandler>
|
template<class MutableBufferSequence, class ReadHandler>
|
||||||
BOOST_ASIO_INITFN_RESULT_TYPE(
|
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||||
ReadHandler, void(error_code, std::size_t))
|
ReadHandler, void(error_code, std::size_t))
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
async_read_some(
|
async_read_some(
|
||||||
MutableBufferSequence const& buffers,
|
MutableBufferSequence const& buffers,
|
||||||
ReadHandler&& handler)
|
ReadHandler&& handler)
|
||||||
|
@ -40,9 +40,9 @@ namespace boost {
|
|||||||
namespace beast {
|
namespace beast {
|
||||||
namespace websocket {
|
namespace websocket {
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class... Args>
|
template<class... Args>
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
stream(Args&&... args)
|
stream(Args&&... args)
|
||||||
: stream_(std::forward<Args>(args)...)
|
: stream_(std::forward<Args>(args)...)
|
||||||
, tok_(1)
|
, tok_(1)
|
||||||
@ -51,16 +51,221 @@ stream(Args&&... args)
|
|||||||
max_control_frame_size);
|
max_control_frame_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
|
template<class DynamicBuffer, class>
|
||||||
std::size_t
|
std::size_t
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
|
read_size_hint(DynamicBuffer& buffer) const
|
||||||
|
{
|
||||||
|
static_assert(
|
||||||
|
boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
|
||||||
|
"DynamicBuffer requirements not met");
|
||||||
|
auto const initial_size = (std::min)(
|
||||||
|
+tcp_frame_size,
|
||||||
|
buffer.max_size() - buffer.size());
|
||||||
|
if(initial_size == 0)
|
||||||
|
return 1; // buffer is full
|
||||||
|
return read_size_hint(initial_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
template<class NextLayer, bool deflateSupported>
|
||||||
|
void
|
||||||
|
stream<NextLayer, deflateSupported>::
|
||||||
|
set_option(permessage_deflate const& o, std::true_type)
|
||||||
|
{
|
||||||
|
if( o.server_max_window_bits > 15 ||
|
||||||
|
o.server_max_window_bits < 9)
|
||||||
|
BOOST_THROW_EXCEPTION(std::invalid_argument{
|
||||||
|
"invalid server_max_window_bits"});
|
||||||
|
if( o.client_max_window_bits > 15 ||
|
||||||
|
o.client_max_window_bits < 9)
|
||||||
|
BOOST_THROW_EXCEPTION(std::invalid_argument{
|
||||||
|
"invalid client_max_window_bits"});
|
||||||
|
if( o.compLevel < 0 ||
|
||||||
|
o.compLevel > 9)
|
||||||
|
BOOST_THROW_EXCEPTION(std::invalid_argument{
|
||||||
|
"invalid compLevel"});
|
||||||
|
if( o.memLevel < 1 ||
|
||||||
|
o.memLevel > 9)
|
||||||
|
BOOST_THROW_EXCEPTION(std::invalid_argument{
|
||||||
|
"invalid memLevel"});
|
||||||
|
this->pmd_opts_ = o;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class NextLayer, bool deflateSupported>
|
||||||
|
void
|
||||||
|
stream<NextLayer, deflateSupported>::
|
||||||
|
set_option(permessage_deflate const& o, std::false_type)
|
||||||
|
{
|
||||||
|
if(o.client_enable || o.server_enable)
|
||||||
|
{
|
||||||
|
// Can't enable permessage-deflate
|
||||||
|
// when deflateSupported == false.
|
||||||
|
//
|
||||||
|
BOOST_THROW_EXCEPTION(std::invalid_argument{
|
||||||
|
"deflateSupported == false"});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class NextLayer, bool deflateSupported>
|
||||||
|
void
|
||||||
|
stream<NextLayer, deflateSupported>::
|
||||||
|
open(role_type role)
|
||||||
|
{
|
||||||
|
// VFALCO TODO analyze and remove dupe code in reset()
|
||||||
|
role_ = role;
|
||||||
|
status_ = status::open;
|
||||||
|
rd_remain_ = 0;
|
||||||
|
rd_cont_ = false;
|
||||||
|
rd_done_ = true;
|
||||||
|
// Can't clear this because accept uses it
|
||||||
|
//rd_buf_.reset();
|
||||||
|
rd_fh_.fin = false;
|
||||||
|
rd_close_ = false;
|
||||||
|
wr_close_ = false;
|
||||||
|
wr_block_.reset();
|
||||||
|
rd_block_.reset();
|
||||||
|
cr_.code = close_code::none;
|
||||||
|
|
||||||
|
wr_cont_ = false;
|
||||||
|
wr_buf_size_ = 0;
|
||||||
|
|
||||||
|
open_pmd(is_deflate_supported{});
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class NextLayer, bool deflateSupported>
|
||||||
|
inline
|
||||||
|
void
|
||||||
|
stream<NextLayer, deflateSupported>::
|
||||||
|
open_pmd(std::true_type)
|
||||||
|
{
|
||||||
|
if(((role_ == role_type::client &&
|
||||||
|
this->pmd_opts_.client_enable) ||
|
||||||
|
(role_ == role_type::server &&
|
||||||
|
this->pmd_opts_.server_enable)) &&
|
||||||
|
this->pmd_config_.accept)
|
||||||
|
{
|
||||||
|
pmd_normalize(this->pmd_config_);
|
||||||
|
this->pmd_.reset(new typename
|
||||||
|
detail::stream_base<deflateSupported>::pmd_type);
|
||||||
|
if(role_ == role_type::client)
|
||||||
|
{
|
||||||
|
this->pmd_->zi.reset(
|
||||||
|
this->pmd_config_.server_max_window_bits);
|
||||||
|
this->pmd_->zo.reset(
|
||||||
|
this->pmd_opts_.compLevel,
|
||||||
|
this->pmd_config_.client_max_window_bits,
|
||||||
|
this->pmd_opts_.memLevel,
|
||||||
|
zlib::Strategy::normal);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->pmd_->zi.reset(
|
||||||
|
this->pmd_config_.client_max_window_bits);
|
||||||
|
this->pmd_->zo.reset(
|
||||||
|
this->pmd_opts_.compLevel,
|
||||||
|
this->pmd_config_.server_max_window_bits,
|
||||||
|
this->pmd_opts_.memLevel,
|
||||||
|
zlib::Strategy::normal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class NextLayer, bool deflateSupported>
|
||||||
|
void
|
||||||
|
stream<NextLayer, deflateSupported>::
|
||||||
|
close()
|
||||||
|
{
|
||||||
|
wr_buf_.reset();
|
||||||
|
close_pmd(is_deflate_supported{});
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class NextLayer, bool deflateSupported>
|
||||||
|
void
|
||||||
|
stream<NextLayer, deflateSupported>::
|
||||||
|
reset()
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(status_ != status::open);
|
||||||
|
rd_remain_ = 0;
|
||||||
|
rd_cont_ = false;
|
||||||
|
rd_done_ = true;
|
||||||
|
rd_buf_.consume(rd_buf_.size());
|
||||||
|
rd_fh_.fin = false;
|
||||||
|
rd_close_ = false;
|
||||||
|
wr_close_ = false;
|
||||||
|
wr_cont_ = false;
|
||||||
|
wr_block_.reset();
|
||||||
|
rd_block_.reset();
|
||||||
|
cr_.code = close_code::none;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called before each write frame
|
||||||
|
template<class NextLayer, bool deflateSupported>
|
||||||
|
inline
|
||||||
|
void
|
||||||
|
stream<NextLayer, deflateSupported>::
|
||||||
|
begin_msg(std::true_type)
|
||||||
|
{
|
||||||
|
wr_frag_ = wr_frag_opt_;
|
||||||
|
wr_compress_ = static_cast<bool>(this->pmd_);
|
||||||
|
|
||||||
|
// Maintain the write buffer
|
||||||
|
if( wr_compress_ ||
|
||||||
|
role_ == role_type::client)
|
||||||
|
{
|
||||||
|
if(! wr_buf_ || wr_buf_size_ != wr_buf_opt_)
|
||||||
|
{
|
||||||
|
wr_buf_size_ = wr_buf_opt_;
|
||||||
|
wr_buf_ = boost::make_unique_noinit<
|
||||||
|
std::uint8_t[]>(wr_buf_size_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wr_buf_size_ = wr_buf_opt_;
|
||||||
|
wr_buf_.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called before each write frame
|
||||||
|
template<class NextLayer, bool deflateSupported>
|
||||||
|
inline
|
||||||
|
void
|
||||||
|
stream<NextLayer, deflateSupported>::
|
||||||
|
begin_msg(std::false_type)
|
||||||
|
{
|
||||||
|
wr_frag_ = wr_frag_opt_;
|
||||||
|
|
||||||
|
// Maintain the write buffer
|
||||||
|
if(role_ == role_type::client)
|
||||||
|
{
|
||||||
|
if(! wr_buf_ || wr_buf_size_ != wr_buf_opt_)
|
||||||
|
{
|
||||||
|
wr_buf_size_ = wr_buf_opt_;
|
||||||
|
wr_buf_ = boost::make_unique_noinit<
|
||||||
|
std::uint8_t[]>(wr_buf_size_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wr_buf_size_ = wr_buf_opt_;
|
||||||
|
wr_buf_.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class NextLayer, bool deflateSupported>
|
||||||
|
std::size_t
|
||||||
|
stream<NextLayer, deflateSupported>::
|
||||||
read_size_hint(
|
read_size_hint(
|
||||||
std::size_t initial_size) const
|
std::size_t initial_size,
|
||||||
|
std::true_type) const
|
||||||
{
|
{
|
||||||
using beast::detail::clamp;
|
using beast::detail::clamp;
|
||||||
std::size_t result;
|
std::size_t result;
|
||||||
BOOST_ASSERT(initial_size > 0);
|
BOOST_ASSERT(initial_size > 0);
|
||||||
if(! pmd_ || (! rd_done_ && ! pmd_->rd_set))
|
if(! this->pmd_ || (! rd_done_ && ! this->pmd_->rd_set))
|
||||||
{
|
{
|
||||||
// current message is uncompressed
|
// current message is uncompressed
|
||||||
|
|
||||||
@ -85,164 +290,45 @@ done:
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class DynamicBuffer, class>
|
|
||||||
std::size_t
|
std::size_t
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
read_size_hint(DynamicBuffer& buffer) const
|
read_size_hint(
|
||||||
|
std::size_t initial_size,
|
||||||
|
std::false_type) const
|
||||||
{
|
{
|
||||||
static_assert(
|
using beast::detail::clamp;
|
||||||
boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
|
std::size_t result;
|
||||||
"DynamicBuffer requirements not met");
|
BOOST_ASSERT(initial_size > 0);
|
||||||
auto const initial_size = (std::min)(
|
// compression is not supported
|
||||||
+tcp_frame_size,
|
if(rd_done_)
|
||||||
buffer.max_size() - buffer.size());
|
|
||||||
if(initial_size == 0)
|
|
||||||
return 1; // buffer is full
|
|
||||||
return read_size_hint(initial_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class NextLayer>
|
|
||||||
void
|
|
||||||
stream<NextLayer>::
|
|
||||||
set_option(permessage_deflate const& o)
|
|
||||||
{
|
|
||||||
if( o.server_max_window_bits > 15 ||
|
|
||||||
o.server_max_window_bits < 9)
|
|
||||||
BOOST_THROW_EXCEPTION(std::invalid_argument{
|
|
||||||
"invalid server_max_window_bits"});
|
|
||||||
if( o.client_max_window_bits > 15 ||
|
|
||||||
o.client_max_window_bits < 9)
|
|
||||||
BOOST_THROW_EXCEPTION(std::invalid_argument{
|
|
||||||
"invalid client_max_window_bits"});
|
|
||||||
if( o.compLevel < 0 ||
|
|
||||||
o.compLevel > 9)
|
|
||||||
BOOST_THROW_EXCEPTION(std::invalid_argument{
|
|
||||||
"invalid compLevel"});
|
|
||||||
if( o.memLevel < 1 ||
|
|
||||||
o.memLevel > 9)
|
|
||||||
BOOST_THROW_EXCEPTION(std::invalid_argument{
|
|
||||||
"invalid memLevel"});
|
|
||||||
pmd_opts_ = o;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
template<class NextLayer>
|
|
||||||
void
|
|
||||||
stream<NextLayer>::
|
|
||||||
open(role_type role)
|
|
||||||
{
|
|
||||||
// VFALCO TODO analyze and remove dupe code in reset()
|
|
||||||
role_ = role;
|
|
||||||
status_ = status::open;
|
|
||||||
rd_remain_ = 0;
|
|
||||||
rd_cont_ = false;
|
|
||||||
rd_done_ = true;
|
|
||||||
// Can't clear this because accept uses it
|
|
||||||
//rd_buf_.reset();
|
|
||||||
rd_fh_.fin = false;
|
|
||||||
rd_close_ = false;
|
|
||||||
wr_close_ = false;
|
|
||||||
wr_block_.reset();
|
|
||||||
rd_block_.reset();
|
|
||||||
cr_.code = close_code::none;
|
|
||||||
|
|
||||||
wr_cont_ = false;
|
|
||||||
wr_buf_size_ = 0;
|
|
||||||
|
|
||||||
if(((role_ == role_type::client && pmd_opts_.client_enable) ||
|
|
||||||
(role_ == role_type::server && pmd_opts_.server_enable)) &&
|
|
||||||
pmd_config_.accept)
|
|
||||||
{
|
{
|
||||||
pmd_normalize(pmd_config_);
|
// first message frame
|
||||||
pmd_.reset(new pmd_t);
|
result = initial_size;
|
||||||
if(role_ == role_type::client)
|
|
||||||
{
|
|
||||||
pmd_->zi.reset(
|
|
||||||
pmd_config_.server_max_window_bits);
|
|
||||||
pmd_->zo.reset(
|
|
||||||
pmd_opts_.compLevel,
|
|
||||||
pmd_config_.client_max_window_bits,
|
|
||||||
pmd_opts_.memLevel,
|
|
||||||
zlib::Strategy::normal);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pmd_->zi.reset(
|
|
||||||
pmd_config_.client_max_window_bits);
|
|
||||||
pmd_->zo.reset(
|
|
||||||
pmd_opts_.compLevel,
|
|
||||||
pmd_config_.server_max_window_bits,
|
|
||||||
pmd_opts_.memLevel,
|
|
||||||
zlib::Strategy::normal);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
else if(rd_fh_.fin)
|
||||||
|
|
||||||
template<class NextLayer>
|
|
||||||
void
|
|
||||||
stream<NextLayer>::
|
|
||||||
close()
|
|
||||||
{
|
|
||||||
wr_buf_.reset();
|
|
||||||
pmd_.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class NextLayer>
|
|
||||||
void
|
|
||||||
stream<NextLayer>::
|
|
||||||
reset()
|
|
||||||
{
|
|
||||||
BOOST_ASSERT(status_ != status::open);
|
|
||||||
rd_remain_ = 0;
|
|
||||||
rd_cont_ = false;
|
|
||||||
rd_done_ = true;
|
|
||||||
rd_buf_.consume(rd_buf_.size());
|
|
||||||
rd_fh_.fin = false;
|
|
||||||
rd_close_ = false;
|
|
||||||
wr_close_ = false;
|
|
||||||
wr_cont_ = false;
|
|
||||||
wr_block_.reset();
|
|
||||||
rd_block_.reset();
|
|
||||||
cr_.code = close_code::none;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Called before each write frame
|
|
||||||
template<class NextLayer>
|
|
||||||
void
|
|
||||||
stream<NextLayer>::
|
|
||||||
begin_msg()
|
|
||||||
{
|
|
||||||
wr_frag_ = wr_frag_opt_;
|
|
||||||
wr_compress_ = static_cast<bool>(pmd_);
|
|
||||||
|
|
||||||
// Maintain the write buffer
|
|
||||||
if( wr_compress_ ||
|
|
||||||
role_ == role_type::client)
|
|
||||||
{
|
{
|
||||||
if(! wr_buf_ || wr_buf_size_ != wr_buf_opt_)
|
// last message frame
|
||||||
{
|
BOOST_ASSERT(rd_remain_ > 0);
|
||||||
wr_buf_size_ = wr_buf_opt_;
|
result = clamp(rd_remain_);
|
||||||
wr_buf_ = boost::make_unique_noinit<
|
|
||||||
std::uint8_t[]>(wr_buf_size_);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
wr_buf_size_ = wr_buf_opt_;
|
result = (std::max)(
|
||||||
wr_buf_.reset();
|
initial_size, clamp(rd_remain_));
|
||||||
}
|
}
|
||||||
|
BOOST_ASSERT(result != 0);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Attempt to read a complete frame header.
|
// Attempt to read a complete frame header.
|
||||||
// Returns `false` if more bytes are needed
|
// Returns `false` if more bytes are needed
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class DynamicBuffer>
|
template<class DynamicBuffer>
|
||||||
bool
|
bool
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
parse_fh(
|
parse_fh(
|
||||||
detail::frame_header& fh,
|
detail::frame_header& fh,
|
||||||
DynamicBuffer& b,
|
DynamicBuffer& b,
|
||||||
@ -301,14 +387,12 @@ parse_fh(
|
|||||||
// new data frame when continuation expected
|
// new data frame when continuation expected
|
||||||
return err(close_code::protocol_error);
|
return err(close_code::protocol_error);
|
||||||
}
|
}
|
||||||
if((fh.rsv1 && ! pmd_) ||
|
if(fh.rsv2 || fh.rsv3 ||
|
||||||
fh.rsv2 || fh.rsv3)
|
! this->rd_deflated(fh.rsv1))
|
||||||
{
|
{
|
||||||
// reserved bits not cleared
|
// reserved bits not cleared
|
||||||
return err(close_code::protocol_error);
|
return err(close_code::protocol_error);
|
||||||
}
|
}
|
||||||
if(pmd_)
|
|
||||||
pmd_->rd_set = fh.rsv1;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case detail::opcode::cont:
|
case detail::opcode::cont:
|
||||||
@ -411,7 +495,7 @@ parse_fh(
|
|||||||
std::uint64_t>::max)() - fh.len)
|
std::uint64_t>::max)() - fh.len)
|
||||||
return err(close_code::too_big);
|
return err(close_code::too_big);
|
||||||
}
|
}
|
||||||
if(! pmd_ || ! pmd_->rd_set)
|
if(! this->rd_deflated())
|
||||||
{
|
{
|
||||||
if(rd_msg_max_ && beast::detail::sum_exceeds(
|
if(rd_msg_max_ && beast::detail::sum_exceeds(
|
||||||
rd_size_, fh.len, rd_msg_max_))
|
rd_size_, fh.len, rd_msg_max_))
|
||||||
@ -425,10 +509,10 @@ parse_fh(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class DynamicBuffer>
|
template<class DynamicBuffer>
|
||||||
void
|
void
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
write_close(DynamicBuffer& db, close_reason const& cr)
|
write_close(DynamicBuffer& db, close_reason const& cr)
|
||||||
{
|
{
|
||||||
using namespace boost::endian;
|
using namespace boost::endian;
|
||||||
@ -479,10 +563,10 @@ write_close(DynamicBuffer& db, close_reason const& cr)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class DynamicBuffer>
|
template<class DynamicBuffer>
|
||||||
void
|
void
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
write_ping(DynamicBuffer& db,
|
write_ping(DynamicBuffer& db,
|
||||||
detail::opcode code, ping_data const& data)
|
detail::opcode code, ping_data const& data)
|
||||||
{
|
{
|
||||||
@ -513,14 +597,13 @@ write_ping(DynamicBuffer& db,
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class Decorator>
|
template<class Decorator>
|
||||||
request_type
|
request_type
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
build_request(detail::sec_ws_key_type& key,
|
build_request(detail::sec_ws_key_type& key,
|
||||||
string_view host,
|
string_view host, string_view target,
|
||||||
string_view target,
|
Decorator const& decorator)
|
||||||
Decorator const& decorator)
|
|
||||||
{
|
{
|
||||||
request_type req;
|
request_type req;
|
||||||
req.target(target);
|
req.target(target);
|
||||||
@ -532,20 +615,7 @@ build_request(detail::sec_ws_key_type& key,
|
|||||||
detail::make_sec_ws_key(key, wr_gen_);
|
detail::make_sec_ws_key(key, wr_gen_);
|
||||||
req.set(http::field::sec_websocket_key, key);
|
req.set(http::field::sec_websocket_key, key);
|
||||||
req.set(http::field::sec_websocket_version, "13");
|
req.set(http::field::sec_websocket_version, "13");
|
||||||
if(pmd_opts_.client_enable)
|
build_request_pmd(req, is_deflate_supported{});
|
||||||
{
|
|
||||||
detail::pmd_offer config;
|
|
||||||
config.accept = true;
|
|
||||||
config.server_max_window_bits =
|
|
||||||
pmd_opts_.server_max_window_bits;
|
|
||||||
config.client_max_window_bits =
|
|
||||||
pmd_opts_.client_max_window_bits;
|
|
||||||
config.server_no_context_takeover =
|
|
||||||
pmd_opts_.server_no_context_takeover;
|
|
||||||
config.client_no_context_takeover =
|
|
||||||
pmd_opts_.client_no_context_takeover;
|
|
||||||
detail::pmd_write(req, config);
|
|
||||||
}
|
|
||||||
decorator(req);
|
decorator(req);
|
||||||
if(! req.count(http::field::user_agent))
|
if(! req.count(http::field::user_agent))
|
||||||
req.set(http::field::user_agent,
|
req.set(http::field::user_agent,
|
||||||
@ -553,13 +623,36 @@ build_request(detail::sec_ws_key_type& key,
|
|||||||
return req;
|
return req;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
|
inline
|
||||||
|
void
|
||||||
|
stream<NextLayer, deflateSupported>::
|
||||||
|
build_request_pmd(request_type& req, std::true_type)
|
||||||
|
{
|
||||||
|
if(this->pmd_opts_.client_enable)
|
||||||
|
{
|
||||||
|
detail::pmd_offer config;
|
||||||
|
config.accept = true;
|
||||||
|
config.server_max_window_bits =
|
||||||
|
this->pmd_opts_.server_max_window_bits;
|
||||||
|
config.client_max_window_bits =
|
||||||
|
this->pmd_opts_.client_max_window_bits;
|
||||||
|
config.server_no_context_takeover =
|
||||||
|
this->pmd_opts_.server_no_context_takeover;
|
||||||
|
config.client_no_context_takeover =
|
||||||
|
this->pmd_opts_.client_no_context_takeover;
|
||||||
|
detail::pmd_write(req, config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class Body, class Allocator, class Decorator>
|
template<class Body, class Allocator, class Decorator>
|
||||||
response_type
|
response_type
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
build_response(http::request<Body,
|
build_response(
|
||||||
http::basic_fields<Allocator>> const& req,
|
http::request<Body,
|
||||||
Decorator const& decorator)
|
http::basic_fields<Allocator>> const& req,
|
||||||
|
Decorator const& decorator)
|
||||||
{
|
{
|
||||||
auto const decorate =
|
auto const decorate =
|
||||||
[&decorator](response_type& res)
|
[&decorator](response_type& res)
|
||||||
@ -614,12 +707,7 @@ build_response(http::request<Body,
|
|||||||
}
|
}
|
||||||
|
|
||||||
response_type res;
|
response_type res;
|
||||||
{
|
build_response_pmd(res, req, is_deflate_supported{});
|
||||||
detail::pmd_offer offer;
|
|
||||||
detail::pmd_offer unused;
|
|
||||||
pmd_read(offer, req);
|
|
||||||
pmd_negotiate(res, unused, offer, pmd_opts_);
|
|
||||||
}
|
|
||||||
res.result(http::status::switching_protocols);
|
res.result(http::status::switching_protocols);
|
||||||
res.version(req.version());
|
res.version(req.version());
|
||||||
res.set(http::field::upgrade, "websocket");
|
res.set(http::field::upgrade, "websocket");
|
||||||
@ -633,11 +721,31 @@ build_response(http::request<Body,
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
|
template<class Body, class Allocator>
|
||||||
|
inline
|
||||||
void
|
void
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
on_response(response_type const& res,
|
build_response_pmd(
|
||||||
detail::sec_ws_key_type const& key, error_code& ec)
|
response_type& res,
|
||||||
|
http::request<Body,
|
||||||
|
http::basic_fields<Allocator>> const& req,
|
||||||
|
std::true_type)
|
||||||
|
{
|
||||||
|
detail::pmd_offer offer;
|
||||||
|
detail::pmd_offer unused;
|
||||||
|
pmd_read(offer, req);
|
||||||
|
pmd_negotiate(res, unused, offer, this->pmd_opts_);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called when the WebSocket Upgrade response is received
|
||||||
|
template<class NextLayer, bool deflateSupported>
|
||||||
|
void
|
||||||
|
stream<NextLayer, deflateSupported>::
|
||||||
|
on_response(
|
||||||
|
response_type const& res,
|
||||||
|
detail::sec_ws_key_type const& key,
|
||||||
|
error_code& ec)
|
||||||
{
|
{
|
||||||
bool const success = [&]()
|
bool const success = [&]()
|
||||||
{
|
{
|
||||||
@ -664,18 +772,29 @@ on_response(response_type const& res,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ec.assign(0, ec.category());
|
ec.assign(0, ec.category());
|
||||||
|
on_response_pmd(res, is_deflate_supported{});
|
||||||
|
open(role_type::client);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class NextLayer, bool deflateSupported>
|
||||||
|
inline
|
||||||
|
void
|
||||||
|
stream<NextLayer, deflateSupported>::
|
||||||
|
on_response_pmd(
|
||||||
|
response_type const& res,
|
||||||
|
std::true_type)
|
||||||
|
{
|
||||||
detail::pmd_offer offer;
|
detail::pmd_offer offer;
|
||||||
pmd_read(offer, res);
|
pmd_read(offer, res);
|
||||||
// VFALCO see if offer satisfies pmd_config_,
|
// VFALCO see if offer satisfies pmd_config_,
|
||||||
// return an error if not.
|
// return an error if not.
|
||||||
pmd_config_ = offer; // overwrite for now
|
this->pmd_config_ = offer; // overwrite for now
|
||||||
open(role_type::client);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// _Fail the WebSocket Connection_
|
// _Fail the WebSocket Connection_
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
void
|
void
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
do_fail(
|
do_fail(
|
||||||
std::uint16_t code, // if set, send a close frame first
|
std::uint16_t code, // if set, send a close frame first
|
||||||
error_code ev, // error code to use upon success
|
error_code ev, // error code to use upon success
|
||||||
|
@ -33,13 +33,113 @@ namespace boost {
|
|||||||
namespace beast {
|
namespace beast {
|
||||||
namespace websocket {
|
namespace websocket {
|
||||||
|
|
||||||
template<class NextLayer>
|
namespace detail {
|
||||||
|
|
||||||
|
// Compress a buffer sequence
|
||||||
|
// Returns: `true` if more calls are needed
|
||||||
|
//
|
||||||
|
template<>
|
||||||
|
template<class ConstBufferSequence>
|
||||||
|
bool
|
||||||
|
stream_base<true>::
|
||||||
|
deflate(
|
||||||
|
boost::asio::mutable_buffer& out,
|
||||||
|
buffers_suffix<ConstBufferSequence>& cb,
|
||||||
|
bool fin,
|
||||||
|
std::size_t& total_in,
|
||||||
|
error_code& ec)
|
||||||
|
{
|
||||||
|
using boost::asio::buffer;
|
||||||
|
BOOST_ASSERT(out.size() >= 6);
|
||||||
|
auto& zo = this->pmd_->zo;
|
||||||
|
zlib::z_params zs;
|
||||||
|
zs.avail_in = 0;
|
||||||
|
zs.next_in = nullptr;
|
||||||
|
zs.avail_out = out.size();
|
||||||
|
zs.next_out = out.data();
|
||||||
|
for(auto in : beast::detail::buffers_range(cb))
|
||||||
|
{
|
||||||
|
zs.avail_in = in.size();
|
||||||
|
if(zs.avail_in == 0)
|
||||||
|
continue;
|
||||||
|
zs.next_in = in.data();
|
||||||
|
zo.write(zs, zlib::Flush::none, ec);
|
||||||
|
if(ec)
|
||||||
|
{
|
||||||
|
if(ec != zlib::error::need_buffers)
|
||||||
|
return false;
|
||||||
|
BOOST_ASSERT(zs.avail_out == 0);
|
||||||
|
BOOST_ASSERT(zs.total_out == out.size());
|
||||||
|
ec.assign(0, ec.category());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(zs.avail_out == 0)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(zs.total_out == out.size());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
BOOST_ASSERT(zs.avail_in == 0);
|
||||||
|
}
|
||||||
|
total_in = zs.total_in;
|
||||||
|
cb.consume(zs.total_in);
|
||||||
|
if(zs.avail_out > 0 && fin)
|
||||||
|
{
|
||||||
|
auto const remain = boost::asio::buffer_size(cb);
|
||||||
|
if(remain == 0)
|
||||||
|
{
|
||||||
|
// Inspired by Mark Adler
|
||||||
|
// https://github.com/madler/zlib/issues/149
|
||||||
|
//
|
||||||
|
// VFALCO We could do this flush twice depending
|
||||||
|
// on how much space is in the output.
|
||||||
|
zo.write(zs, zlib::Flush::block, ec);
|
||||||
|
BOOST_ASSERT(! ec || ec == zlib::error::need_buffers);
|
||||||
|
if(ec == zlib::error::need_buffers)
|
||||||
|
ec.assign(0, ec.category());
|
||||||
|
if(ec)
|
||||||
|
return false;
|
||||||
|
if(zs.avail_out >= 6)
|
||||||
|
{
|
||||||
|
zo.write(zs, zlib::Flush::full, ec);
|
||||||
|
BOOST_ASSERT(! ec);
|
||||||
|
// remove flush marker
|
||||||
|
zs.total_out -= 4;
|
||||||
|
out = buffer(out.data(), zs.total_out);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ec.assign(0, ec.category());
|
||||||
|
out = buffer(out.data(), zs.total_out);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline
|
||||||
|
void
|
||||||
|
stream_base<true>::
|
||||||
|
do_context_takeover_write(role_type role)
|
||||||
|
{
|
||||||
|
if((role == role_type::client &&
|
||||||
|
this->pmd_config_.client_no_context_takeover) ||
|
||||||
|
(role == role_type::server &&
|
||||||
|
this->pmd_config_.server_no_context_takeover))
|
||||||
|
{
|
||||||
|
this->pmd_->zo.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // detail
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class Buffers, class Handler>
|
template<class Buffers, class Handler>
|
||||||
class stream<NextLayer>::write_some_op
|
class stream<NextLayer, deflateSupported>::write_some_op
|
||||||
: public boost::asio::coroutine
|
: public boost::asio::coroutine
|
||||||
{
|
{
|
||||||
Handler h_;
|
Handler h_;
|
||||||
stream<NextLayer>& ws_;
|
stream<NextLayer, deflateSupported>& ws_;
|
||||||
buffers_suffix<Buffers> cb_;
|
buffers_suffix<Buffers> cb_;
|
||||||
detail::frame_header fh_;
|
detail::frame_header fh_;
|
||||||
detail::prepared_key key_;
|
detail::prepared_key key_;
|
||||||
@ -59,7 +159,7 @@ public:
|
|||||||
template<class DeducedHandler>
|
template<class DeducedHandler>
|
||||||
write_some_op(
|
write_some_op(
|
||||||
DeducedHandler&& h,
|
DeducedHandler&& h,
|
||||||
stream<NextLayer>& ws,
|
stream<NextLayer, deflateSupported>& ws,
|
||||||
bool fin,
|
bool fin,
|
||||||
Buffers const& bs)
|
Buffers const& bs)
|
||||||
: h_(std::forward<DeducedHandler>(h))
|
: h_(std::forward<DeducedHandler>(h))
|
||||||
@ -80,7 +180,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
using executor_type = boost::asio::associated_executor_t<
|
using executor_type = boost::asio::associated_executor_t<
|
||||||
Handler, decltype(std::declval<stream<NextLayer>&>().get_executor())>;
|
Handler, decltype(std::declval<stream<NextLayer, deflateSupported>&>().get_executor())>;
|
||||||
|
|
||||||
executor_type
|
executor_type
|
||||||
get_executor() const noexcept
|
get_executor() const noexcept
|
||||||
@ -109,10 +209,10 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class Buffers, class Handler>
|
template<class Buffers, class Handler>
|
||||||
void
|
void
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
write_some_op<Buffers, Handler>::
|
write_some_op<Buffers, Handler>::
|
||||||
operator()(
|
operator()(
|
||||||
error_code ec,
|
error_code ec,
|
||||||
@ -397,8 +497,7 @@ operator()(
|
|||||||
{
|
{
|
||||||
b = buffer(ws_.wr_buf_.get(),
|
b = buffer(ws_.wr_buf_.get(),
|
||||||
ws_.wr_buf_size_);
|
ws_.wr_buf_size_);
|
||||||
more_ = detail::deflate(ws_.pmd_->zo,
|
more_ = ws_.deflate(b, cb_, fin_, in_, ec);
|
||||||
b, cb_, fin_, in_, ec);
|
|
||||||
if(! ws_.check_ok(ec))
|
if(! ws_.check_ok(ec))
|
||||||
goto upcall;
|
goto upcall;
|
||||||
n = buffer_size(b);
|
n = buffer_size(b);
|
||||||
@ -450,12 +549,8 @@ operator()(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(fh_.fin && (
|
if(fh_.fin)
|
||||||
(ws_.role_ == role_type::client &&
|
ws_.do_context_takeover_write(ws_.role_);
|
||||||
ws_.pmd_config_.client_no_context_takeover) ||
|
|
||||||
(ws_.role_ == role_type::server &&
|
|
||||||
ws_.pmd_config_.server_no_context_takeover)))
|
|
||||||
ws_.pmd_->zo.reset();
|
|
||||||
goto upcall;
|
goto upcall;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -479,10 +574,10 @@ operator()(
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class ConstBufferSequence>
|
template<class ConstBufferSequence>
|
||||||
std::size_t
|
std::size_t
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
write_some(bool fin, ConstBufferSequence const& buffers)
|
write_some(bool fin, ConstBufferSequence const& buffers)
|
||||||
{
|
{
|
||||||
static_assert(is_sync_stream<next_layer_type>::value,
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
@ -498,10 +593,10 @@ write_some(bool fin, ConstBufferSequence const& buffers)
|
|||||||
return bytes_transferred;
|
return bytes_transferred;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class ConstBufferSequence>
|
template<class ConstBufferSequence>
|
||||||
std::size_t
|
std::size_t
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
write_some(bool fin,
|
write_some(bool fin,
|
||||||
ConstBufferSequence const& buffers, error_code& ec)
|
ConstBufferSequence const& buffers, error_code& ec)
|
||||||
{
|
{
|
||||||
@ -543,9 +638,8 @@ write_some(bool fin,
|
|||||||
{
|
{
|
||||||
auto b = buffer(
|
auto b = buffer(
|
||||||
wr_buf_.get(), wr_buf_size_);
|
wr_buf_.get(), wr_buf_size_);
|
||||||
auto const more = detail::deflate(
|
auto const more = this->deflate(
|
||||||
pmd_->zo, b, cb, fin,
|
b, cb, fin, bytes_transferred, ec);
|
||||||
bytes_transferred, ec);
|
|
||||||
if(! check_ok(ec))
|
if(! check_ok(ec))
|
||||||
return bytes_transferred;
|
return bytes_transferred;
|
||||||
auto const n = buffer_size(b);
|
auto const n = buffer_size(b);
|
||||||
@ -581,12 +675,8 @@ write_some(bool fin,
|
|||||||
fh.op = detail::opcode::cont;
|
fh.op = detail::opcode::cont;
|
||||||
fh.rsv1 = false;
|
fh.rsv1 = false;
|
||||||
}
|
}
|
||||||
if(fh.fin && (
|
if(fh.fin)
|
||||||
(role_ == role_type::client &&
|
this->do_context_takeover_write(role_);
|
||||||
pmd_config_.client_no_context_takeover) ||
|
|
||||||
(role_ == role_type::server &&
|
|
||||||
pmd_config_.server_no_context_takeover)))
|
|
||||||
pmd_->zo.reset();
|
|
||||||
}
|
}
|
||||||
else if(! fh.mask)
|
else if(! fh.mask)
|
||||||
{
|
{
|
||||||
@ -711,11 +801,11 @@ write_some(bool fin,
|
|||||||
return bytes_transferred;
|
return bytes_transferred;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class ConstBufferSequence, class WriteHandler>
|
template<class ConstBufferSequence, class WriteHandler>
|
||||||
BOOST_ASIO_INITFN_RESULT_TYPE(
|
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||||
WriteHandler, void(error_code, std::size_t))
|
WriteHandler, void(error_code, std::size_t))
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
async_write_some(bool fin,
|
async_write_some(bool fin,
|
||||||
ConstBufferSequence const& bs, WriteHandler&& handler)
|
ConstBufferSequence const& bs, WriteHandler&& handler)
|
||||||
{
|
{
|
||||||
@ -735,10 +825,10 @@ async_write_some(bool fin,
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class ConstBufferSequence>
|
template<class ConstBufferSequence>
|
||||||
std::size_t
|
std::size_t
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
write(ConstBufferSequence const& buffers)
|
write(ConstBufferSequence const& buffers)
|
||||||
{
|
{
|
||||||
static_assert(is_sync_stream<next_layer_type>::value,
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
@ -753,10 +843,10 @@ write(ConstBufferSequence const& buffers)
|
|||||||
return bytes_transferred;
|
return bytes_transferred;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class ConstBufferSequence>
|
template<class ConstBufferSequence>
|
||||||
std::size_t
|
std::size_t
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
write(ConstBufferSequence const& buffers, error_code& ec)
|
write(ConstBufferSequence const& buffers, error_code& ec)
|
||||||
{
|
{
|
||||||
static_assert(is_sync_stream<next_layer_type>::value,
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
@ -767,11 +857,11 @@ write(ConstBufferSequence const& buffers, error_code& ec)
|
|||||||
return write_some(true, buffers, ec);
|
return write_some(true, buffers, ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class ConstBufferSequence, class WriteHandler>
|
template<class ConstBufferSequence, class WriteHandler>
|
||||||
BOOST_ASIO_INITFN_RESULT_TYPE(
|
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||||
WriteHandler, void(error_code, std::size_t))
|
WriteHandler, void(error_code, std::size_t))
|
||||||
stream<NextLayer>::
|
stream<NextLayer, deflateSupported>::
|
||||||
async_write(
|
async_write(
|
||||||
ConstBufferSequence const& bs, WriteHandler&& handler)
|
ConstBufferSequence const& bs, WriteHandler&& handler)
|
||||||
{
|
{
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include <boost/beast/websocket/detail/mask.hpp>
|
#include <boost/beast/websocket/detail/mask.hpp>
|
||||||
#include <boost/beast/websocket/detail/pausation.hpp>
|
#include <boost/beast/websocket/detail/pausation.hpp>
|
||||||
#include <boost/beast/websocket/detail/pmd_extension.hpp>
|
#include <boost/beast/websocket/detail/pmd_extension.hpp>
|
||||||
|
#include <boost/beast/websocket/detail/stream_base.hpp>
|
||||||
#include <boost/beast/websocket/detail/utf8_checker.hpp>
|
#include <boost/beast/websocket/detail/utf8_checker.hpp>
|
||||||
#include <boost/beast/core/static_buffer.hpp>
|
#include <boost/beast/core/static_buffer.hpp>
|
||||||
#include <boost/beast/core/string.hpp>
|
#include <boost/beast/core/string.hpp>
|
||||||
@ -29,8 +30,6 @@
|
|||||||
#include <boost/beast/http/message.hpp>
|
#include <boost/beast/http/message.hpp>
|
||||||
#include <boost/beast/http/string_body.hpp>
|
#include <boost/beast/http/string_body.hpp>
|
||||||
#include <boost/beast/http/detail/type_traits.hpp>
|
#include <boost/beast/http/detail/type_traits.hpp>
|
||||||
#include <boost/beast/zlib/deflate_stream.hpp>
|
|
||||||
#include <boost/beast/zlib/inflate_stream.hpp>
|
|
||||||
#include <boost/asio/async_result.hpp>
|
#include <boost/asio/async_result.hpp>
|
||||||
#include <boost/asio/error.hpp>
|
#include <boost/asio/error.hpp>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@ -108,6 +107,12 @@ class frame_test;
|
|||||||
For asynchronous operations, the type must support the
|
For asynchronous operations, the type must support the
|
||||||
@b AsyncStream concept.
|
@b AsyncStream concept.
|
||||||
|
|
||||||
|
@tparam deflateSupported A `bool` indicating whether or not the
|
||||||
|
stream will be capable of negotiating the permessage-deflate websocket
|
||||||
|
extension. Note that even if this is set to `true`, the permessage
|
||||||
|
deflate options (set by the caller at runtime) must still have the
|
||||||
|
feature enabled for a successful negotiation to occur.
|
||||||
|
|
||||||
@note A stream object must not be moved or destroyed while there
|
@note A stream object must not be moved or destroyed while there
|
||||||
are pending asynchronous operations associated with it.
|
are pending asynchronous operations associated with it.
|
||||||
|
|
||||||
@ -116,8 +121,13 @@ class frame_test;
|
|||||||
@b DynamicBuffer,
|
@b DynamicBuffer,
|
||||||
@b SyncStream
|
@b SyncStream
|
||||||
*/
|
*/
|
||||||
template<class NextLayer>
|
template<
|
||||||
|
class NextLayer,
|
||||||
|
bool deflateSupported>
|
||||||
class stream
|
class stream
|
||||||
|
#ifndef BOOST_BEAST_DOXYGEN
|
||||||
|
: private detail::stream_base<deflateSupported>
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
friend class close_test;
|
friend class close_test;
|
||||||
friend class frame_test;
|
friend class frame_test;
|
||||||
@ -126,7 +136,7 @@ class stream
|
|||||||
friend class read2_test;
|
friend class read2_test;
|
||||||
friend class stream_test;
|
friend class stream_test;
|
||||||
friend class write_test;
|
friend class write_test;
|
||||||
|
|
||||||
/* The read buffer has to be at least as large
|
/* The read buffer has to be at least as large
|
||||||
as the largest possible control frame including
|
as the largest possible control frame including
|
||||||
the frame header.
|
the frame header.
|
||||||
@ -134,8 +144,6 @@ class stream
|
|||||||
static std::size_t constexpr max_control_frame_size = 2 + 8 + 4 + 125;
|
static std::size_t constexpr max_control_frame_size = 2 + 8 + 4 + 125;
|
||||||
static std::size_t constexpr tcp_frame_size = 1536;
|
static std::size_t constexpr tcp_frame_size = 1536;
|
||||||
|
|
||||||
struct op {};
|
|
||||||
|
|
||||||
using control_cb_type =
|
using control_cb_type =
|
||||||
std::function<void(frame_type, string_view)>;
|
std::function<void(frame_type, string_view)>;
|
||||||
|
|
||||||
@ -154,16 +162,6 @@ class stream
|
|||||||
void reset() { id_ = 0; }
|
void reset() { id_ = 0; }
|
||||||
};
|
};
|
||||||
|
|
||||||
// State information for the permessage-deflate extension
|
|
||||||
struct pmd_t
|
|
||||||
{
|
|
||||||
// `true` if current read message is compressed
|
|
||||||
bool rd_set = false;
|
|
||||||
|
|
||||||
zlib::deflate_stream zo;
|
|
||||||
zlib::inflate_stream zi;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class status
|
enum class status
|
||||||
{
|
{
|
||||||
open,
|
open,
|
||||||
@ -231,14 +229,14 @@ class stream
|
|||||||
detail::pausation paused_wr_; // paused write op
|
detail::pausation paused_wr_; // paused write op
|
||||||
detail::pausation paused_ping_; // paused ping op
|
detail::pausation paused_ping_; // paused ping op
|
||||||
detail::pausation paused_close_; // paused close op
|
detail::pausation paused_close_; // paused close op
|
||||||
detail::pausation paused_r_rd_; // paused read op (read)
|
detail::pausation paused_r_rd_; // paused read op (async read)
|
||||||
detail::pausation paused_r_close_;// paused close op (read)
|
detail::pausation paused_r_close_;// paused close op (async read)
|
||||||
|
|
||||||
std::unique_ptr<pmd_t> pmd_; // pmd settings or nullptr
|
|
||||||
permessage_deflate pmd_opts_; // local pmd options
|
|
||||||
detail::pmd_offer pmd_config_; // offer (client) or negotiation (server)
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
/// Indicates if the permessage-deflate extension is supported
|
||||||
|
using is_deflate_supported =
|
||||||
|
std::integral_constant<bool, deflateSupported>;
|
||||||
|
|
||||||
/// The type of the next layer.
|
/// The type of the next layer.
|
||||||
using next_layer_type =
|
using next_layer_type =
|
||||||
typename std::remove_reference<NextLayer>::type;
|
typename std::remove_reference<NextLayer>::type;
|
||||||
@ -444,7 +442,11 @@ public:
|
|||||||
*/
|
*/
|
||||||
std::size_t
|
std::size_t
|
||||||
read_size_hint(
|
read_size_hint(
|
||||||
std::size_t initial_size = +tcp_frame_size) const;
|
std::size_t initial_size = +tcp_frame_size) const
|
||||||
|
{
|
||||||
|
return read_size_hint(initial_size,
|
||||||
|
is_deflate_supported{});
|
||||||
|
}
|
||||||
|
|
||||||
/** Returns a suggested maximum buffer size for the next call to read.
|
/** Returns a suggested maximum buffer size for the next call to read.
|
||||||
|
|
||||||
@ -475,15 +477,22 @@ public:
|
|||||||
//
|
//
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
/// Set the permessage-deflate extension options
|
/** Set the permessage-deflate extension options
|
||||||
|
|
||||||
|
@throws invalid_argument if `deflateSupported == false`, and either
|
||||||
|
`client_enable` or `server_enable` is `true`.
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
set_option(permessage_deflate const& o);
|
set_option(permessage_deflate const& o)
|
||||||
|
{
|
||||||
|
set_option(o, is_deflate_supported{});
|
||||||
|
}
|
||||||
|
|
||||||
/// Get the permessage-deflate extension options
|
/// Get the permessage-deflate extension options
|
||||||
void
|
void
|
||||||
get_option(permessage_deflate& o)
|
get_option(permessage_deflate& o)
|
||||||
{
|
{
|
||||||
o = pmd_opts_;
|
get_option(o, is_deflate_supported{});
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Set the automatic fragmentation option.
|
/** Set the automatic fragmentation option.
|
||||||
@ -2353,8 +2362,8 @@ public:
|
|||||||
next layer's `async_write_some` functions, and is known as a
|
next layer's `async_write_some` functions, and is known as a
|
||||||
<em>composed operation</em>. The program must ensure that the
|
<em>composed operation</em>. The program must ensure that the
|
||||||
stream performs no other write operations (such as @ref async_ping,
|
stream performs no other write operations (such as @ref async_ping,
|
||||||
@ref stream::async_write, @ref stream::async_write_some, or
|
@ref async_write, @ref async_write_some, or @ref async_close)
|
||||||
@ref stream::async_close) until this operation completes.
|
until this operation completes.
|
||||||
|
|
||||||
If the close reason specifies a close code other than
|
If the close reason specifies a close code other than
|
||||||
@ref beast::websocket::close_code::none, the close frame is
|
@ref beast::websocket::close_code::none, the close frame is
|
||||||
@ -3172,8 +3181,8 @@ public:
|
|||||||
to the next layer's `async_write_some` functions, and is known
|
to the next layer's `async_write_some` functions, and is known
|
||||||
as a <em>composed operation</em>. The program must ensure that
|
as a <em>composed operation</em>. The program must ensure that
|
||||||
the stream performs no other write operations (such as
|
the stream performs no other write operations (such as
|
||||||
stream::async_write, stream::async_write_some, or
|
@ref async_write, @ref async_write_some, or
|
||||||
stream::async_close).
|
@ref async_close).
|
||||||
|
|
||||||
The current setting of the @ref binary option controls
|
The current setting of the @ref binary option controls
|
||||||
whether the message opcode is set to text or binary. If the
|
whether the message opcode is set to text or binary. If the
|
||||||
@ -3301,8 +3310,8 @@ public:
|
|||||||
as a <em>composed operation</em>. The actual payload sent
|
as a <em>composed operation</em>. The actual payload sent
|
||||||
may be transformed as per the WebSocket protocol settings. The
|
may be transformed as per the WebSocket protocol settings. The
|
||||||
program must ensure that the stream performs no other write
|
program must ensure that the stream performs no other write
|
||||||
operations (such as stream::async_write, stream::async_write_some,
|
operations (such as @ref async_write, @ref async_write_some,
|
||||||
or stream::async_close).
|
or @ref async_close).
|
||||||
|
|
||||||
If this is the beginning of a new message, the message opcode
|
If this is the beginning of a new message, the message opcode
|
||||||
will be set to text or binary as per the current setting of
|
will be set to text or binary as per the current setting of
|
||||||
@ -3351,10 +3360,65 @@ private:
|
|||||||
static void default_decorate_req(request_type&) {}
|
static void default_decorate_req(request_type&) {}
|
||||||
static void default_decorate_res(response_type&) {}
|
static void default_decorate_res(response_type&) {}
|
||||||
|
|
||||||
|
void
|
||||||
|
set_option(permessage_deflate const& o, std::true_type);
|
||||||
|
|
||||||
|
void
|
||||||
|
set_option(permessage_deflate const&, std::false_type);
|
||||||
|
|
||||||
|
void
|
||||||
|
get_option(permessage_deflate& o, std::true_type)
|
||||||
|
{
|
||||||
|
o = this->pmd_opts_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
get_option(permessage_deflate& o, std::false_type)
|
||||||
|
{
|
||||||
|
o = {};
|
||||||
|
o.client_enable = false;
|
||||||
|
o.server_enable = false;
|
||||||
|
}
|
||||||
|
|
||||||
void open(role_type role);
|
void open(role_type role);
|
||||||
|
|
||||||
|
void open_pmd(std::true_type);
|
||||||
|
|
||||||
|
void open_pmd(std::false_type)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void close();
|
void close();
|
||||||
|
|
||||||
|
void close_pmd(std::true_type)
|
||||||
|
{
|
||||||
|
this->pmd_.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void close_pmd(std::false_type)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
void begin_msg();
|
|
||||||
|
void begin_msg()
|
||||||
|
{
|
||||||
|
begin_msg(is_deflate_supported{});
|
||||||
|
}
|
||||||
|
|
||||||
|
void begin_msg(std::true_type);
|
||||||
|
|
||||||
|
void begin_msg(std::false_type);
|
||||||
|
|
||||||
|
std::size_t
|
||||||
|
read_size_hint(
|
||||||
|
std::size_t initial_size,
|
||||||
|
std::true_type) const;
|
||||||
|
|
||||||
|
std::size_t
|
||||||
|
read_size_hint(
|
||||||
|
std::size_t initial_size,
|
||||||
|
std::false_type) const;
|
||||||
|
|
||||||
bool
|
bool
|
||||||
check_open(error_code& ec)
|
check_open(error_code& ec)
|
||||||
@ -3394,6 +3458,10 @@ private:
|
|||||||
write_ping(DynamicBuffer& b,
|
write_ping(DynamicBuffer& b,
|
||||||
detail::opcode op, ping_data const& data);
|
detail::opcode op, ping_data const& data);
|
||||||
|
|
||||||
|
//
|
||||||
|
// upgrade
|
||||||
|
//
|
||||||
|
|
||||||
template<class Decorator>
|
template<class Decorator>
|
||||||
request_type
|
request_type
|
||||||
build_request(detail::sec_ws_key_type& key,
|
build_request(detail::sec_ws_key_type& key,
|
||||||
@ -3401,28 +3469,94 @@ private:
|
|||||||
string_view target,
|
string_view target,
|
||||||
Decorator const& decorator);
|
Decorator const& decorator);
|
||||||
|
|
||||||
template<class Body,
|
void
|
||||||
class Allocator, class Decorator>
|
build_request_pmd(request_type& req, std::true_type);
|
||||||
response_type
|
|
||||||
build_response(http::request<Body,
|
|
||||||
http::basic_fields<Allocator>> const& req,
|
|
||||||
Decorator const& decorator);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
on_response(response_type const& resp,
|
build_request_pmd(request_type&, std::false_type)
|
||||||
detail::sec_ws_key_type const& key, error_code& ec);
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template<
|
||||||
|
class Body, class Allocator, class Decorator>
|
||||||
|
response_type
|
||||||
|
build_response(
|
||||||
|
http::request<Body,
|
||||||
|
http::basic_fields<Allocator>> const& req,
|
||||||
|
Decorator const& decorator);
|
||||||
|
|
||||||
|
template<class Body, class Allocator>
|
||||||
|
void
|
||||||
|
build_response_pmd(
|
||||||
|
response_type& res,
|
||||||
|
http::request<Body,
|
||||||
|
http::basic_fields<Allocator>> const& req,
|
||||||
|
std::true_type);
|
||||||
|
|
||||||
|
template<class Body, class Allocator>
|
||||||
|
void
|
||||||
|
build_response_pmd(
|
||||||
|
response_type&,
|
||||||
|
http::request<Body,
|
||||||
|
http::basic_fields<Allocator>> const&,
|
||||||
|
std::false_type)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
on_response(
|
||||||
|
response_type const& res,
|
||||||
|
detail::sec_ws_key_type const& key,
|
||||||
|
error_code& ec);
|
||||||
|
|
||||||
|
void
|
||||||
|
on_response_pmd(
|
||||||
|
response_type const& res,
|
||||||
|
std::true_type);
|
||||||
|
|
||||||
|
void
|
||||||
|
on_response_pmd(
|
||||||
|
response_type const&,
|
||||||
|
std::false_type)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// accept / handshake
|
||||||
|
//
|
||||||
|
|
||||||
|
template<class Allocator>
|
||||||
|
void
|
||||||
|
do_pmd_config(
|
||||||
|
http::basic_fields<Allocator> const& h,
|
||||||
|
std::true_type)
|
||||||
|
{
|
||||||
|
pmd_read(this->pmd_config_, h);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Allocator>
|
||||||
|
void
|
||||||
|
do_pmd_config(
|
||||||
|
http::basic_fields<Allocator> const&,
|
||||||
|
std::false_type)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
template<class Decorator>
|
template<class Decorator>
|
||||||
void
|
void
|
||||||
do_accept(Decorator const& decorator,
|
do_accept(
|
||||||
|
Decorator const& decorator,
|
||||||
error_code& ec);
|
error_code& ec);
|
||||||
|
|
||||||
template<class Body, class Allocator,
|
template<
|
||||||
|
class Body, class Allocator,
|
||||||
class Decorator>
|
class Decorator>
|
||||||
void
|
void
|
||||||
do_accept(http::request<Body,
|
do_accept(
|
||||||
http::basic_fields<Allocator>> const& req,
|
http::request<Body,
|
||||||
Decorator const& decorator, error_code& ec);
|
http::basic_fields<Allocator>> const& req,
|
||||||
|
Decorator const& decorator,
|
||||||
|
error_code& ec);
|
||||||
|
|
||||||
template<class RequestDecorator>
|
template<class RequestDecorator>
|
||||||
void
|
void
|
||||||
@ -3431,6 +3565,10 @@ private:
|
|||||||
RequestDecorator const& decorator,
|
RequestDecorator const& decorator,
|
||||||
error_code& ec);
|
error_code& ec);
|
||||||
|
|
||||||
|
//
|
||||||
|
// fail
|
||||||
|
//
|
||||||
|
|
||||||
void
|
void
|
||||||
do_fail(
|
do_fail(
|
||||||
std::uint16_t code,
|
std::uint16_t code,
|
||||||
|
@ -17,7 +17,8 @@ namespace beast {
|
|||||||
namespace websocket {
|
namespace websocket {
|
||||||
|
|
||||||
template<
|
template<
|
||||||
class NextLayer>
|
class NextLayer,
|
||||||
|
bool deflateSupported = true>
|
||||||
class stream;
|
class stream;
|
||||||
|
|
||||||
} // websocket
|
} // websocket
|
||||||
|
@ -23,11 +23,11 @@ namespace websocket {
|
|||||||
class read1_test : public websocket_test_suite
|
class read1_test : public websocket_test_suite
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
template<class Wrap>
|
template<class Wrap, bool deflateSupported>
|
||||||
void
|
void
|
||||||
doReadTest(
|
doReadTest(
|
||||||
Wrap const& w,
|
Wrap const& w,
|
||||||
ws_type& ws,
|
ws_type_t<deflateSupported>& ws,
|
||||||
close_code code)
|
close_code code)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@ -45,11 +45,11 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Wrap>
|
template<class Wrap, bool deflateSupported>
|
||||||
void
|
void
|
||||||
doFailTest(
|
doFailTest(
|
||||||
Wrap const& w,
|
Wrap const& w,
|
||||||
ws_type& ws,
|
ws_type_t<deflateSupported>& ws,
|
||||||
error_code ev)
|
error_code ev)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@ -65,7 +65,7 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Wrap>
|
template<bool deflateSupported = true, class Wrap>
|
||||||
void
|
void
|
||||||
doTestRead(Wrap const& w)
|
doTestRead(Wrap const& w)
|
||||||
{
|
{
|
||||||
@ -78,7 +78,7 @@ public:
|
|||||||
// already closed
|
// already closed
|
||||||
{
|
{
|
||||||
echo_server es{log};
|
echo_server es{log};
|
||||||
stream<test::stream> ws{ioc_};
|
stream<test::stream, deflateSupported> ws{ioc_};
|
||||||
ws.next_layer().connect(es.stream());
|
ws.next_layer().connect(es.stream());
|
||||||
ws.handshake("localhost", "/");
|
ws.handshake("localhost", "/");
|
||||||
ws.close({});
|
ws.close({});
|
||||||
@ -97,7 +97,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// empty, fragmented message
|
// empty, fragmented message
|
||||||
doTest(pmd, [&](ws_type& ws)
|
doTest<deflateSupported>(pmd,
|
||||||
|
[&](ws_type_t<deflateSupported>& ws)
|
||||||
{
|
{
|
||||||
ws.next_layer().append(
|
ws.next_layer().append(
|
||||||
string_view(
|
string_view(
|
||||||
@ -109,7 +110,8 @@ public:
|
|||||||
|
|
||||||
// two part message
|
// two part message
|
||||||
// triggers "fill the read buffer first"
|
// triggers "fill the read buffer first"
|
||||||
doTest(pmd, [&](ws_type& ws)
|
doTest<deflateSupported>(pmd,
|
||||||
|
[&](ws_type_t<deflateSupported>& ws)
|
||||||
{
|
{
|
||||||
w.write_raw(ws, sbuf(
|
w.write_raw(ws, sbuf(
|
||||||
"\x01\x81\xff\xff\xff\xff"));
|
"\x01\x81\xff\xff\xff\xff"));
|
||||||
@ -123,7 +125,8 @@ public:
|
|||||||
});
|
});
|
||||||
|
|
||||||
// ping
|
// ping
|
||||||
doTest(pmd, [&](ws_type& ws)
|
doTest<deflateSupported>(pmd,
|
||||||
|
[&](ws_type_t<deflateSupported>& ws)
|
||||||
{
|
{
|
||||||
put(ws.next_layer().buffer(), cbuf(
|
put(ws.next_layer().buffer(), cbuf(
|
||||||
0x89, 0x00));
|
0x89, 0x00));
|
||||||
@ -144,7 +147,8 @@ public:
|
|||||||
});
|
});
|
||||||
|
|
||||||
// ping
|
// ping
|
||||||
doTest(pmd, [&](ws_type& ws)
|
doTest<deflateSupported>(pmd,
|
||||||
|
[&](ws_type_t<deflateSupported>& ws)
|
||||||
{
|
{
|
||||||
put(ws.next_layer().buffer(), cbuf(
|
put(ws.next_layer().buffer(), cbuf(
|
||||||
0x88, 0x00));
|
0x88, 0x00));
|
||||||
@ -161,7 +165,8 @@ public:
|
|||||||
});
|
});
|
||||||
|
|
||||||
// ping then message
|
// ping then message
|
||||||
doTest(pmd, [&](ws_type& ws)
|
doTest<deflateSupported>(pmd,
|
||||||
|
[&](ws_type_t<deflateSupported>& ws)
|
||||||
{
|
{
|
||||||
bool once = false;
|
bool once = false;
|
||||||
ws.control_callback(
|
ws.control_callback(
|
||||||
@ -183,7 +188,8 @@ public:
|
|||||||
});
|
});
|
||||||
|
|
||||||
// ping then fragmented message
|
// ping then fragmented message
|
||||||
doTest(pmd, [&](ws_type& ws)
|
doTest<deflateSupported>(pmd,
|
||||||
|
[&](ws_type_t<deflateSupported>& ws)
|
||||||
{
|
{
|
||||||
bool once = false;
|
bool once = false;
|
||||||
ws.control_callback(
|
ws.control_callback(
|
||||||
@ -208,7 +214,7 @@ public:
|
|||||||
doStreamLoop([&](test::stream& ts)
|
doStreamLoop([&](test::stream& ts)
|
||||||
{
|
{
|
||||||
echo_server es{log, kind::async_client};
|
echo_server es{log, kind::async_client};
|
||||||
ws_type ws{ts};
|
ws_type_t<deflateSupported> ws{ts};
|
||||||
ws.next_layer().connect(es.stream());
|
ws.next_layer().connect(es.stream());
|
||||||
ws.set_option(pmd);
|
ws.set_option(pmd);
|
||||||
es.async_handshake();
|
es.async_handshake();
|
||||||
@ -237,7 +243,7 @@ public:
|
|||||||
{
|
{
|
||||||
echo_server es{log, kind::async};
|
echo_server es{log, kind::async};
|
||||||
boost::asio::io_context ioc;
|
boost::asio::io_context ioc;
|
||||||
stream<test::stream> ws{ioc, fc};
|
stream<test::stream, deflateSupported> ws{ioc, fc};
|
||||||
ws.next_layer().connect(es.stream());
|
ws.next_layer().connect(es.stream());
|
||||||
ws.handshake("localhost", "/");
|
ws.handshake("localhost", "/");
|
||||||
// Cause close to be received
|
// Cause close to be received
|
||||||
@ -257,7 +263,8 @@ public:
|
|||||||
});
|
});
|
||||||
|
|
||||||
// already closed
|
// already closed
|
||||||
doTest(pmd, [&](ws_type& ws)
|
doTest<deflateSupported>(pmd,
|
||||||
|
[&](ws_type_t<deflateSupported>& ws)
|
||||||
{
|
{
|
||||||
w.close(ws, {});
|
w.close(ws, {});
|
||||||
multi_buffer b;
|
multi_buffer b;
|
||||||
@ -266,7 +273,8 @@ public:
|
|||||||
});
|
});
|
||||||
|
|
||||||
// buffer overflow
|
// buffer overflow
|
||||||
doTest(pmd, [&](ws_type& ws)
|
doTest<deflateSupported>(pmd,
|
||||||
|
[&](ws_type_t<deflateSupported>& ws)
|
||||||
{
|
{
|
||||||
std::string const s = "Hello, world!";
|
std::string const s = "Hello, world!";
|
||||||
ws.auto_fragment(false);
|
ws.auto_fragment(false);
|
||||||
@ -286,7 +294,8 @@ public:
|
|||||||
});
|
});
|
||||||
|
|
||||||
// bad utf8, big
|
// bad utf8, big
|
||||||
doTest(pmd, [&](ws_type& ws)
|
doTest<deflateSupported>(pmd,
|
||||||
|
[&](ws_type_t<deflateSupported>& ws)
|
||||||
{
|
{
|
||||||
auto const s = std::string(2000, '*') +
|
auto const s = std::string(2000, '*') +
|
||||||
random_string();
|
random_string();
|
||||||
@ -296,7 +305,8 @@ public:
|
|||||||
});
|
});
|
||||||
|
|
||||||
// invalid fixed frame header
|
// invalid fixed frame header
|
||||||
doTest(pmd, [&](ws_type& ws)
|
doTest<deflateSupported>(pmd,
|
||||||
|
[&](ws_type_t<deflateSupported>& ws)
|
||||||
{
|
{
|
||||||
w.write_raw(ws, cbuf(
|
w.write_raw(ws, cbuf(
|
||||||
0x8f, 0x80, 0xff, 0xff, 0xff, 0xff));
|
0x8f, 0x80, 0xff, 0xff, 0xff, 0xff));
|
||||||
@ -304,7 +314,8 @@ public:
|
|||||||
});
|
});
|
||||||
|
|
||||||
// bad close
|
// bad close
|
||||||
doTest(pmd, [&](ws_type& ws)
|
doTest<deflateSupported>(pmd,
|
||||||
|
[&](ws_type_t<deflateSupported>& ws)
|
||||||
{
|
{
|
||||||
put(ws.next_layer().buffer(), cbuf(
|
put(ws.next_layer().buffer(), cbuf(
|
||||||
0x88, 0x02, 0x03, 0xed));
|
0x88, 0x02, 0x03, 0xed));
|
||||||
@ -312,7 +323,8 @@ public:
|
|||||||
});
|
});
|
||||||
|
|
||||||
// message size above 2^64
|
// message size above 2^64
|
||||||
doTest(pmd, [&](ws_type& ws)
|
doTest<deflateSupported>(pmd,
|
||||||
|
[&](ws_type_t<deflateSupported>& ws)
|
||||||
{
|
{
|
||||||
w.write_some(ws, false, sbuf("*"));
|
w.write_some(ws, false, sbuf("*"));
|
||||||
w.write_raw(ws, cbuf(
|
w.write_raw(ws, cbuf(
|
||||||
@ -322,7 +334,8 @@ public:
|
|||||||
});
|
});
|
||||||
|
|
||||||
// message size exceeds max
|
// message size exceeds max
|
||||||
doTest(pmd, [&](ws_type& ws)
|
doTest<deflateSupported>(pmd,
|
||||||
|
[&](ws_type_t<deflateSupported>& ws)
|
||||||
{
|
{
|
||||||
ws.read_message_max(1);
|
ws.read_message_max(1);
|
||||||
w.write(ws, sbuf("**"));
|
w.write(ws, sbuf("**"));
|
||||||
@ -330,7 +343,8 @@ public:
|
|||||||
});
|
});
|
||||||
|
|
||||||
// bad utf8
|
// bad utf8
|
||||||
doTest(pmd, [&](ws_type& ws)
|
doTest<deflateSupported>(pmd,
|
||||||
|
[&](ws_type_t<deflateSupported>& ws)
|
||||||
{
|
{
|
||||||
put(ws.next_layer().buffer(), cbuf(
|
put(ws.next_layer().buffer(), cbuf(
|
||||||
0x81, 0x06, 0x03, 0xea, 0xf0, 0x28, 0x8c, 0xbc));
|
0x81, 0x06, 0x03, 0xea, 0xf0, 0x28, 0x8c, 0xbc));
|
||||||
@ -338,7 +352,8 @@ public:
|
|||||||
});
|
});
|
||||||
|
|
||||||
// incomplete utf8
|
// incomplete utf8
|
||||||
doTest(pmd, [&](ws_type& ws)
|
doTest<deflateSupported>(pmd,
|
||||||
|
[&](ws_type_t<deflateSupported>& ws)
|
||||||
{
|
{
|
||||||
std::string const s =
|
std::string const s =
|
||||||
"Hello, world!" "\xc0";
|
"Hello, world!" "\xc0";
|
||||||
@ -347,7 +362,8 @@ public:
|
|||||||
});
|
});
|
||||||
|
|
||||||
// incomplete utf8, big
|
// incomplete utf8, big
|
||||||
doTest(pmd, [&](ws_type& ws)
|
doTest<deflateSupported>(pmd,
|
||||||
|
[&](ws_type_t<deflateSupported>& ws)
|
||||||
{
|
{
|
||||||
std::string const s =
|
std::string const s =
|
||||||
"\x81\x7e\x0f\xa1" +
|
"\x81\x7e\x0f\xa1" +
|
||||||
@ -375,7 +391,7 @@ public:
|
|||||||
[&](error_code ev, string_view s)
|
[&](error_code ev, string_view s)
|
||||||
{
|
{
|
||||||
echo_server es{log};
|
echo_server es{log};
|
||||||
stream<test::stream> ws{ioc_};
|
stream<test::stream, deflateSupported> ws{ioc_};
|
||||||
ws.next_layer().connect(es.stream());
|
ws.next_layer().connect(es.stream());
|
||||||
w.handshake(ws, "localhost", "/");
|
w.handshake(ws, "localhost", "/");
|
||||||
ws.next_layer().append(s);
|
ws.next_layer().append(s);
|
||||||
@ -410,11 +426,15 @@ public:
|
|||||||
check(error::closed,
|
check(error::closed,
|
||||||
"\x88\x06\xfc\x15utf8");
|
"\x88\x06\xfc\x15utf8");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//
|
template<class Wrap>
|
||||||
// permessage-deflate
|
void
|
||||||
//
|
doTestReadDeflate(Wrap const& w)
|
||||||
|
{
|
||||||
|
using boost::asio::buffer;
|
||||||
|
|
||||||
|
permessage_deflate pmd;
|
||||||
pmd.client_enable = true;
|
pmd.client_enable = true;
|
||||||
pmd.server_enable = true;
|
pmd.server_enable = true;
|
||||||
pmd.client_max_window_bits = 9;
|
pmd.client_max_window_bits = 9;
|
||||||
@ -422,7 +442,8 @@ public:
|
|||||||
pmd.compLevel = 1;
|
pmd.compLevel = 1;
|
||||||
|
|
||||||
// message size limit
|
// message size limit
|
||||||
doTest(pmd, [&](ws_type& ws)
|
doTest<true>(pmd,
|
||||||
|
[&](ws_type_t<true>& ws)
|
||||||
{
|
{
|
||||||
std::string const s = std::string(128, '*');
|
std::string const s = std::string(128, '*');
|
||||||
w.write(ws, buffer(s));
|
w.write(ws, buffer(s));
|
||||||
@ -431,7 +452,8 @@ public:
|
|||||||
});
|
});
|
||||||
|
|
||||||
// invalid inflate block
|
// invalid inflate block
|
||||||
doTest(pmd, [&](ws_type& ws)
|
doTest<true>(pmd,
|
||||||
|
[&](ws_type_t<true>& ws)
|
||||||
{
|
{
|
||||||
auto const& s = random_string();
|
auto const& s = random_string();
|
||||||
ws.binary(true);
|
ws.binary(true);
|
||||||
@ -458,7 +480,8 @@ public:
|
|||||||
|
|
||||||
// no_context_takeover
|
// no_context_takeover
|
||||||
pmd.server_no_context_takeover = true;
|
pmd.server_no_context_takeover = true;
|
||||||
doTest(pmd, [&](ws_type& ws)
|
doTest<true>(pmd,
|
||||||
|
[&](ws_type_t<true>& ws)
|
||||||
{
|
{
|
||||||
auto const& s = random_string();
|
auto const& s = random_string();
|
||||||
ws.binary(true);
|
ws.binary(true);
|
||||||
@ -587,10 +610,14 @@ public:
|
|||||||
{
|
{
|
||||||
using boost::asio::buffer;
|
using boost::asio::buffer;
|
||||||
|
|
||||||
doTestRead(SyncClient{});
|
doTestRead<false>(SyncClient{});
|
||||||
|
doTestRead<true>(SyncClient{});
|
||||||
|
doTestReadDeflate(SyncClient{});
|
||||||
yield_to([&](yield_context yield)
|
yield_to([&](yield_context yield)
|
||||||
{
|
{
|
||||||
doTestRead(AsyncClient{yield});
|
doTestRead<false>(AsyncClient{yield});
|
||||||
|
doTestRead<true>(AsyncClient{yield});
|
||||||
|
doTestReadDeflate(AsyncClient{yield});
|
||||||
});
|
});
|
||||||
|
|
||||||
permessage_deflate pmd;
|
permessage_deflate pmd;
|
||||||
|
@ -122,6 +122,8 @@ public:
|
|||||||
BOOST_STATIC_ASSERT(! std::is_move_assignable<
|
BOOST_STATIC_ASSERT(! std::is_move_assignable<
|
||||||
stream<test::stream&>>::value);
|
stream<test::stream&>>::value);
|
||||||
|
|
||||||
|
log << "sizeof(websocket::stream_base<true>) == " <<
|
||||||
|
sizeof(websocket::detail::stream_base<true>) << std::endl;
|
||||||
log << "sizeof(websocket::stream) == " <<
|
log << "sizeof(websocket::stream) == " <<
|
||||||
sizeof(websocket::stream<test::stream&>) << std::endl;
|
sizeof(websocket::stream<test::stream&>) << std::endl;
|
||||||
|
|
||||||
|
@ -35,6 +35,10 @@ class websocket_test_suite
|
|||||||
, public test::enable_yield_to
|
, public test::enable_yield_to
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
template<bool deflateSupported>
|
||||||
|
using ws_type_t =
|
||||||
|
websocket::stream<test::stream&, deflateSupported>;
|
||||||
|
|
||||||
using ws_type =
|
using ws_type =
|
||||||
websocket::stream<test::stream&>;
|
websocket::stream<test::stream&>;
|
||||||
|
|
||||||
@ -303,7 +307,7 @@ public:
|
|||||||
, limit);
|
, limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Test>
|
template<bool deflateSupported = true, class Test>
|
||||||
void
|
void
|
||||||
doTest(
|
doTest(
|
||||||
permessage_deflate const& pmd,
|
permessage_deflate const& pmd,
|
||||||
@ -320,7 +324,7 @@ public:
|
|||||||
{
|
{
|
||||||
test::fail_counter fc{n};
|
test::fail_counter fc{n};
|
||||||
test::stream ts{ioc_, fc};
|
test::stream ts{ioc_, fc};
|
||||||
ws_type ws{ts};
|
ws_type_t<deflateSupported> ws{ts};
|
||||||
ws.set_option(pmd);
|
ws.set_option(pmd);
|
||||||
|
|
||||||
echo_server es{log, i==1 ?
|
echo_server es{log, i==1 ?
|
||||||
@ -481,146 +485,171 @@ public:
|
|||||||
|
|
||||||
struct SyncClient
|
struct SyncClient
|
||||||
{
|
{
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
void
|
void
|
||||||
accept(stream<NextLayer>& ws) const
|
accept(
|
||||||
|
stream<NextLayer, deflateSupported>& ws) const
|
||||||
{
|
{
|
||||||
ws.accept();
|
ws.accept();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer, class Buffers>
|
template<
|
||||||
|
class NextLayer, bool deflateSupported,
|
||||||
|
class Buffers>
|
||||||
typename std::enable_if<
|
typename std::enable_if<
|
||||||
! http::detail::is_header<Buffers>::value>::type
|
! http::detail::is_header<Buffers>::value>::type
|
||||||
accept(stream<NextLayer>& ws,
|
accept(stream<NextLayer, deflateSupported>& ws,
|
||||||
Buffers const& buffers) const
|
Buffers const& buffers) const
|
||||||
{
|
{
|
||||||
ws.accept(buffers);
|
ws.accept(buffers);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
void
|
void
|
||||||
accept(stream<NextLayer>& ws,
|
accept(
|
||||||
|
stream<NextLayer, deflateSupported>& ws,
|
||||||
http::request<http::empty_body> const& req) const
|
http::request<http::empty_body> const& req) const
|
||||||
{
|
{
|
||||||
ws.accept(req);
|
ws.accept(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer, class Decorator>
|
template<
|
||||||
|
class NextLayer, bool deflateSupported,
|
||||||
|
class Decorator>
|
||||||
void
|
void
|
||||||
accept_ex(stream<NextLayer>& ws,
|
accept_ex(
|
||||||
|
stream<NextLayer, deflateSupported>& ws,
|
||||||
Decorator const& d) const
|
Decorator const& d) const
|
||||||
{
|
{
|
||||||
ws.accept_ex(d);
|
ws.accept_ex(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer,
|
template<
|
||||||
|
class NextLayer, bool deflateSupported,
|
||||||
class Buffers, class Decorator>
|
class Buffers, class Decorator>
|
||||||
typename std::enable_if<
|
typename std::enable_if<
|
||||||
! http::detail::is_header<Buffers>::value>::type
|
! http::detail::is_header<Buffers>::value>::type
|
||||||
accept_ex(stream<NextLayer>& ws,
|
accept_ex(
|
||||||
|
stream<NextLayer, deflateSupported>& ws,
|
||||||
Buffers const& buffers,
|
Buffers const& buffers,
|
||||||
Decorator const& d) const
|
Decorator const& d) const
|
||||||
{
|
{
|
||||||
ws.accept_ex(buffers, d);
|
ws.accept_ex(buffers, d);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer, class Decorator>
|
template<
|
||||||
|
class NextLayer, bool deflateSupported,
|
||||||
|
class Decorator>
|
||||||
void
|
void
|
||||||
accept_ex(stream<NextLayer>& ws,
|
accept_ex(
|
||||||
|
stream<NextLayer, deflateSupported>& ws,
|
||||||
http::request<http::empty_body> const& req,
|
http::request<http::empty_body> const& req,
|
||||||
Decorator const& d) const
|
Decorator const& d) const
|
||||||
{
|
{
|
||||||
ws.accept_ex(req, d);
|
ws.accept_ex(req, d);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer,
|
template<
|
||||||
|
class NextLayer, bool deflateSupported,
|
||||||
class Buffers, class Decorator>
|
class Buffers, class Decorator>
|
||||||
void
|
void
|
||||||
accept_ex(stream<NextLayer>& ws,
|
accept_ex(
|
||||||
|
stream<NextLayer, deflateSupported>& ws,
|
||||||
http::request<http::empty_body> const& req,
|
http::request<http::empty_body> const& req,
|
||||||
Buffers const& buffers,
|
Buffers const& buffers,
|
||||||
Decorator const& d) const
|
Decorator const& d) const
|
||||||
{
|
{
|
||||||
ws.accept_ex(req, buffers, d);
|
ws.accept_ex(req, buffers, d);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
void
|
void
|
||||||
handshake(stream<NextLayer>& ws,
|
handshake(
|
||||||
|
stream<NextLayer, deflateSupported>& ws,
|
||||||
string_view uri,
|
string_view uri,
|
||||||
string_view path) const
|
string_view path) const
|
||||||
{
|
{
|
||||||
ws.handshake(uri, path);
|
ws.handshake(uri, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
void
|
void
|
||||||
handshake(stream<NextLayer>& ws,
|
handshake(
|
||||||
|
stream<NextLayer, deflateSupported>& ws,
|
||||||
response_type& res,
|
response_type& res,
|
||||||
string_view uri,
|
string_view uri,
|
||||||
string_view path) const
|
string_view path) const
|
||||||
{
|
{
|
||||||
ws.handshake(res, uri, path);
|
ws.handshake(res, uri, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer, class Decorator>
|
template<
|
||||||
|
class NextLayer, bool deflateSupported,
|
||||||
|
class Decorator>
|
||||||
void
|
void
|
||||||
handshake_ex(stream<NextLayer>& ws,
|
handshake_ex(
|
||||||
|
stream<NextLayer, deflateSupported>& ws,
|
||||||
string_view uri,
|
string_view uri,
|
||||||
string_view path,
|
string_view path,
|
||||||
Decorator const& d) const
|
Decorator const& d) const
|
||||||
{
|
{
|
||||||
ws.handshake_ex(uri, path, d);
|
ws.handshake_ex(uri, path, d);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer, class Decorator>
|
template<
|
||||||
|
class NextLayer, bool deflateSupported,
|
||||||
|
class Decorator>
|
||||||
void
|
void
|
||||||
handshake_ex(stream<NextLayer>& ws,
|
handshake_ex(
|
||||||
|
stream<NextLayer, deflateSupported>& ws,
|
||||||
response_type& res,
|
response_type& res,
|
||||||
string_view uri,
|
string_view uri,
|
||||||
string_view path,
|
string_view path,
|
||||||
Decorator const& d) const
|
Decorator const& d) const
|
||||||
{
|
{
|
||||||
ws.handshake_ex(res, uri, path, d);
|
ws.handshake_ex(res, uri, path, d);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
void
|
void
|
||||||
ping(stream<NextLayer>& ws,
|
ping(stream<NextLayer, deflateSupported>& ws,
|
||||||
ping_data const& payload) const
|
ping_data const& payload) const
|
||||||
{
|
{
|
||||||
ws.ping(payload);
|
ws.ping(payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
void
|
void
|
||||||
pong(stream<NextLayer>& ws,
|
pong(stream<NextLayer, deflateSupported>& ws,
|
||||||
ping_data const& payload) const
|
ping_data const& payload) const
|
||||||
{
|
{
|
||||||
ws.pong(payload);
|
ws.pong(payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
void
|
void
|
||||||
close(stream<NextLayer>& ws,
|
close(stream<NextLayer, deflateSupported>& ws,
|
||||||
close_reason const& cr) const
|
close_reason const& cr) const
|
||||||
{
|
{
|
||||||
ws.close(cr);
|
ws.close(cr);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<
|
template<
|
||||||
class NextLayer, class DynamicBuffer>
|
class NextLayer, bool deflateSupported,
|
||||||
|
class DynamicBuffer>
|
||||||
std::size_t
|
std::size_t
|
||||||
read(stream<NextLayer>& ws,
|
read(stream<NextLayer, deflateSupported>& ws,
|
||||||
DynamicBuffer& buffer) const
|
DynamicBuffer& buffer) const
|
||||||
{
|
{
|
||||||
return ws.read(buffer);
|
return ws.read(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<
|
template<
|
||||||
class NextLayer, class DynamicBuffer>
|
class NextLayer, bool deflateSupported,
|
||||||
|
class DynamicBuffer>
|
||||||
std::size_t
|
std::size_t
|
||||||
read_some(stream<NextLayer>& ws,
|
read_some(
|
||||||
|
stream<NextLayer, deflateSupported>& ws,
|
||||||
std::size_t limit,
|
std::size_t limit,
|
||||||
DynamicBuffer& buffer) const
|
DynamicBuffer& buffer) const
|
||||||
{
|
{
|
||||||
@ -628,36 +657,45 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<
|
template<
|
||||||
class NextLayer, class MutableBufferSequence>
|
class NextLayer, bool deflateSupported,
|
||||||
|
class MutableBufferSequence>
|
||||||
std::size_t
|
std::size_t
|
||||||
read_some(stream<NextLayer>& ws,
|
read_some(
|
||||||
|
stream<NextLayer, deflateSupported>& ws,
|
||||||
MutableBufferSequence const& buffers) const
|
MutableBufferSequence const& buffers) const
|
||||||
{
|
{
|
||||||
return ws.read_some(buffers);
|
return ws.read_some(buffers);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<
|
template<
|
||||||
class NextLayer, class ConstBufferSequence>
|
class NextLayer, bool deflateSupported,
|
||||||
|
class ConstBufferSequence>
|
||||||
std::size_t
|
std::size_t
|
||||||
write(stream<NextLayer>& ws,
|
write(
|
||||||
|
stream<NextLayer, deflateSupported>& ws,
|
||||||
ConstBufferSequence const& buffers) const
|
ConstBufferSequence const& buffers) const
|
||||||
{
|
{
|
||||||
return ws.write(buffers);
|
return ws.write(buffers);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<
|
template<
|
||||||
class NextLayer, class ConstBufferSequence>
|
class NextLayer, bool deflateSupported,
|
||||||
|
class ConstBufferSequence>
|
||||||
std::size_t
|
std::size_t
|
||||||
write_some(stream<NextLayer>& ws, bool fin,
|
write_some(
|
||||||
|
stream<NextLayer, deflateSupported>& ws,
|
||||||
|
bool fin,
|
||||||
ConstBufferSequence const& buffers) const
|
ConstBufferSequence const& buffers) const
|
||||||
{
|
{
|
||||||
return ws.write_some(fin, buffers);
|
return ws.write_some(fin, buffers);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<
|
template<
|
||||||
class NextLayer, class ConstBufferSequence>
|
class NextLayer, bool deflateSupported,
|
||||||
|
class ConstBufferSequence>
|
||||||
std::size_t
|
std::size_t
|
||||||
write_raw(stream<NextLayer>& ws,
|
write_raw(
|
||||||
|
stream<NextLayer, deflateSupported>& ws,
|
||||||
ConstBufferSequence const& buffers) const
|
ConstBufferSequence const& buffers) const
|
||||||
{
|
{
|
||||||
return boost::asio::write(
|
return boost::asio::write(
|
||||||
@ -678,9 +716,9 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
void
|
void
|
||||||
accept(stream<NextLayer>& ws) const
|
accept(stream<NextLayer, deflateSupported>& ws) const
|
||||||
{
|
{
|
||||||
error_code ec;
|
error_code ec;
|
||||||
ws.async_accept(yield_[ec]);
|
ws.async_accept(yield_[ec]);
|
||||||
@ -688,10 +726,13 @@ public:
|
|||||||
throw system_error{ec};
|
throw system_error{ec};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer, class Buffers>
|
template<
|
||||||
|
class NextLayer, bool deflateSupported,
|
||||||
|
class Buffers>
|
||||||
typename std::enable_if<
|
typename std::enable_if<
|
||||||
! http::detail::is_header<Buffers>::value>::type
|
! http::detail::is_header<Buffers>::value>::type
|
||||||
accept(stream<NextLayer>& ws,
|
accept(
|
||||||
|
stream<NextLayer, deflateSupported>& ws,
|
||||||
Buffers const& buffers) const
|
Buffers const& buffers) const
|
||||||
{
|
{
|
||||||
error_code ec;
|
error_code ec;
|
||||||
@ -700,9 +741,10 @@ public:
|
|||||||
throw system_error{ec};
|
throw system_error{ec};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
void
|
void
|
||||||
accept(stream<NextLayer>& ws,
|
accept(
|
||||||
|
stream<NextLayer, deflateSupported>& ws,
|
||||||
http::request<http::empty_body> const& req) const
|
http::request<http::empty_body> const& req) const
|
||||||
{
|
{
|
||||||
error_code ec;
|
error_code ec;
|
||||||
@ -711,10 +753,12 @@ public:
|
|||||||
throw system_error{ec};
|
throw system_error{ec};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer,
|
template<
|
||||||
|
class NextLayer, bool deflateSupported,
|
||||||
class Decorator>
|
class Decorator>
|
||||||
void
|
void
|
||||||
accept_ex(stream<NextLayer>& ws,
|
accept_ex(
|
||||||
|
stream<NextLayer, deflateSupported>& ws,
|
||||||
Decorator const& d) const
|
Decorator const& d) const
|
||||||
{
|
{
|
||||||
error_code ec;
|
error_code ec;
|
||||||
@ -723,13 +767,15 @@ public:
|
|||||||
throw system_error{ec};
|
throw system_error{ec};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer,
|
template<
|
||||||
|
class NextLayer, bool deflateSupported,
|
||||||
class Buffers, class Decorator>
|
class Buffers, class Decorator>
|
||||||
typename std::enable_if<
|
typename std::enable_if<
|
||||||
! http::detail::is_header<Buffers>::value>::type
|
! http::detail::is_header<Buffers>::value>::type
|
||||||
accept_ex(stream<NextLayer>& ws,
|
accept_ex(
|
||||||
|
stream<NextLayer, deflateSupported>& ws,
|
||||||
Buffers const& buffers,
|
Buffers const& buffers,
|
||||||
Decorator const& d) const
|
Decorator const& d) const
|
||||||
{
|
{
|
||||||
error_code ec;
|
error_code ec;
|
||||||
ws.async_accept_ex(buffers, d, yield_[ec]);
|
ws.async_accept_ex(buffers, d, yield_[ec]);
|
||||||
@ -737,11 +783,14 @@ public:
|
|||||||
throw system_error{ec};
|
throw system_error{ec};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer, class Decorator>
|
template<
|
||||||
|
class NextLayer, bool deflateSupported,
|
||||||
|
class Decorator>
|
||||||
void
|
void
|
||||||
accept_ex(stream<NextLayer>& ws,
|
accept_ex(
|
||||||
|
stream<NextLayer, deflateSupported>& ws,
|
||||||
http::request<http::empty_body> const& req,
|
http::request<http::empty_body> const& req,
|
||||||
Decorator const& d) const
|
Decorator const& d) const
|
||||||
{
|
{
|
||||||
error_code ec;
|
error_code ec;
|
||||||
ws.async_accept_ex(req, d, yield_[ec]);
|
ws.async_accept_ex(req, d, yield_[ec]);
|
||||||
@ -749,13 +798,15 @@ public:
|
|||||||
throw system_error{ec};
|
throw system_error{ec};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer,
|
template<
|
||||||
|
class NextLayer, bool deflateSupported,
|
||||||
class Buffers, class Decorator>
|
class Buffers, class Decorator>
|
||||||
void
|
void
|
||||||
accept_ex(stream<NextLayer>& ws,
|
accept_ex(
|
||||||
|
stream<NextLayer, deflateSupported>& ws,
|
||||||
http::request<http::empty_body> const& req,
|
http::request<http::empty_body> const& req,
|
||||||
Buffers const& buffers,
|
Buffers const& buffers,
|
||||||
Decorator const& d) const
|
Decorator const& d) const
|
||||||
{
|
{
|
||||||
error_code ec;
|
error_code ec;
|
||||||
ws.async_accept_ex(
|
ws.async_accept_ex(
|
||||||
@ -764,11 +815,13 @@ public:
|
|||||||
throw system_error{ec};
|
throw system_error{ec};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<
|
||||||
|
class NextLayer, bool deflateSupported>
|
||||||
void
|
void
|
||||||
handshake(stream<NextLayer>& ws,
|
handshake(
|
||||||
|
stream<NextLayer, deflateSupported>& ws,
|
||||||
string_view uri,
|
string_view uri,
|
||||||
string_view path) const
|
string_view path) const
|
||||||
{
|
{
|
||||||
error_code ec;
|
error_code ec;
|
||||||
ws.async_handshake(
|
ws.async_handshake(
|
||||||
@ -777,12 +830,13 @@ public:
|
|||||||
throw system_error{ec};
|
throw system_error{ec};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
void
|
void
|
||||||
handshake(stream<NextLayer>& ws,
|
handshake(
|
||||||
|
stream<NextLayer, deflateSupported>& ws,
|
||||||
response_type& res,
|
response_type& res,
|
||||||
string_view uri,
|
string_view uri,
|
||||||
string_view path) const
|
string_view path) const
|
||||||
{
|
{
|
||||||
error_code ec;
|
error_code ec;
|
||||||
ws.async_handshake(
|
ws.async_handshake(
|
||||||
@ -791,12 +845,15 @@ public:
|
|||||||
throw system_error{ec};
|
throw system_error{ec};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer, class Decorator>
|
template<
|
||||||
|
class NextLayer, bool deflateSupported,
|
||||||
|
class Decorator>
|
||||||
void
|
void
|
||||||
handshake_ex(stream<NextLayer>& ws,
|
handshake_ex(
|
||||||
|
stream<NextLayer, deflateSupported>& ws,
|
||||||
string_view uri,
|
string_view uri,
|
||||||
string_view path,
|
string_view path,
|
||||||
Decorator const &d) const
|
Decorator const &d) const
|
||||||
{
|
{
|
||||||
error_code ec;
|
error_code ec;
|
||||||
ws.async_handshake_ex(
|
ws.async_handshake_ex(
|
||||||
@ -805,13 +862,16 @@ public:
|
|||||||
throw system_error{ec};
|
throw system_error{ec};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer, class Decorator>
|
template<
|
||||||
|
class NextLayer, bool deflateSupported,
|
||||||
|
class Decorator>
|
||||||
void
|
void
|
||||||
handshake_ex(stream<NextLayer>& ws,
|
handshake_ex(
|
||||||
|
stream<NextLayer, deflateSupported>& ws,
|
||||||
response_type& res,
|
response_type& res,
|
||||||
string_view uri,
|
string_view uri,
|
||||||
string_view path,
|
string_view path,
|
||||||
Decorator const &d) const
|
Decorator const &d) const
|
||||||
{
|
{
|
||||||
error_code ec;
|
error_code ec;
|
||||||
ws.async_handshake_ex(
|
ws.async_handshake_ex(
|
||||||
@ -820,9 +880,10 @@ public:
|
|||||||
throw system_error{ec};
|
throw system_error{ec};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
void
|
void
|
||||||
ping(stream<NextLayer>& ws,
|
ping(
|
||||||
|
stream<NextLayer, deflateSupported>& ws,
|
||||||
ping_data const& payload) const
|
ping_data const& payload) const
|
||||||
{
|
{
|
||||||
error_code ec;
|
error_code ec;
|
||||||
@ -831,9 +892,10 @@ public:
|
|||||||
throw system_error{ec};
|
throw system_error{ec};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
void
|
void
|
||||||
pong(stream<NextLayer>& ws,
|
pong(
|
||||||
|
stream<NextLayer, deflateSupported>& ws,
|
||||||
ping_data const& payload) const
|
ping_data const& payload) const
|
||||||
{
|
{
|
||||||
error_code ec;
|
error_code ec;
|
||||||
@ -842,9 +904,10 @@ public:
|
|||||||
throw system_error{ec};
|
throw system_error{ec};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer, bool deflateSupported>
|
||||||
void
|
void
|
||||||
close(stream<NextLayer>& ws,
|
close(
|
||||||
|
stream<NextLayer, deflateSupported>& ws,
|
||||||
close_reason const& cr) const
|
close_reason const& cr) const
|
||||||
{
|
{
|
||||||
error_code ec;
|
error_code ec;
|
||||||
@ -854,9 +917,11 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<
|
template<
|
||||||
class NextLayer, class DynamicBuffer>
|
class NextLayer, bool deflateSupported,
|
||||||
|
class DynamicBuffer>
|
||||||
std::size_t
|
std::size_t
|
||||||
read(stream<NextLayer>& ws,
|
read(
|
||||||
|
stream<NextLayer, deflateSupported>& ws,
|
||||||
DynamicBuffer& buffer) const
|
DynamicBuffer& buffer) const
|
||||||
{
|
{
|
||||||
error_code ec;
|
error_code ec;
|
||||||
@ -868,9 +933,11 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<
|
template<
|
||||||
class NextLayer, class DynamicBuffer>
|
class NextLayer, bool deflateSupported,
|
||||||
|
class DynamicBuffer>
|
||||||
std::size_t
|
std::size_t
|
||||||
read_some(stream<NextLayer>& ws,
|
read_some(
|
||||||
|
stream<NextLayer, deflateSupported>& ws,
|
||||||
std::size_t limit,
|
std::size_t limit,
|
||||||
DynamicBuffer& buffer) const
|
DynamicBuffer& buffer) const
|
||||||
{
|
{
|
||||||
@ -883,9 +950,11 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<
|
template<
|
||||||
class NextLayer, class MutableBufferSequence>
|
class NextLayer, bool deflateSupported,
|
||||||
|
class MutableBufferSequence>
|
||||||
std::size_t
|
std::size_t
|
||||||
read_some(stream<NextLayer>& ws,
|
read_some(
|
||||||
|
stream<NextLayer, deflateSupported>& ws,
|
||||||
MutableBufferSequence const& buffers) const
|
MutableBufferSequence const& buffers) const
|
||||||
{
|
{
|
||||||
error_code ec;
|
error_code ec;
|
||||||
@ -897,9 +966,11 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<
|
template<
|
||||||
class NextLayer, class ConstBufferSequence>
|
class NextLayer, bool deflateSupported,
|
||||||
|
class ConstBufferSequence>
|
||||||
std::size_t
|
std::size_t
|
||||||
write(stream<NextLayer>& ws,
|
write(
|
||||||
|
stream<NextLayer, deflateSupported>& ws,
|
||||||
ConstBufferSequence const& buffers) const
|
ConstBufferSequence const& buffers) const
|
||||||
{
|
{
|
||||||
error_code ec;
|
error_code ec;
|
||||||
@ -911,9 +982,12 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<
|
template<
|
||||||
class NextLayer, class ConstBufferSequence>
|
class NextLayer, bool deflateSupported,
|
||||||
|
class ConstBufferSequence>
|
||||||
std::size_t
|
std::size_t
|
||||||
write_some(stream<NextLayer>& ws, bool fin,
|
write_some(
|
||||||
|
stream<NextLayer, deflateSupported>& ws,
|
||||||
|
bool fin,
|
||||||
ConstBufferSequence const& buffers) const
|
ConstBufferSequence const& buffers) const
|
||||||
{
|
{
|
||||||
error_code ec;
|
error_code ec;
|
||||||
@ -925,9 +999,11 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<
|
template<
|
||||||
class NextLayer, class ConstBufferSequence>
|
class NextLayer, bool deflateSupported,
|
||||||
|
class ConstBufferSequence>
|
||||||
std::size_t
|
std::size_t
|
||||||
write_raw(stream<NextLayer>& ws,
|
write_raw(
|
||||||
|
stream<NextLayer, deflateSupported>& ws,
|
||||||
ConstBufferSequence const& buffers) const
|
ConstBufferSequence const& buffers) const
|
||||||
{
|
{
|
||||||
error_code ec;
|
error_code ec;
|
||||||
|
@ -19,7 +19,7 @@ namespace websocket {
|
|||||||
class write_test : public websocket_test_suite
|
class write_test : public websocket_test_suite
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
template<class Wrap>
|
template<bool deflateSupported, class Wrap>
|
||||||
void
|
void
|
||||||
doTestWrite(Wrap const& w)
|
doTestWrite(Wrap const& w)
|
||||||
{
|
{
|
||||||
@ -50,7 +50,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// message
|
// message
|
||||||
doTest(pmd, [&](ws_type& ws)
|
doTest<deflateSupported>(pmd,
|
||||||
|
[&](ws_type_t<deflateSupported>& ws)
|
||||||
{
|
{
|
||||||
ws.auto_fragment(false);
|
ws.auto_fragment(false);
|
||||||
ws.binary(false);
|
ws.binary(false);
|
||||||
@ -63,7 +64,8 @@ public:
|
|||||||
});
|
});
|
||||||
|
|
||||||
// empty message
|
// empty message
|
||||||
doTest(pmd, [&](ws_type& ws)
|
doTest<deflateSupported>(pmd,
|
||||||
|
[&](ws_type_t<deflateSupported>& ws)
|
||||||
{
|
{
|
||||||
ws.text(true);
|
ws.text(true);
|
||||||
w.write(ws, boost::asio::const_buffer{});
|
w.write(ws, boost::asio::const_buffer{});
|
||||||
@ -74,7 +76,8 @@ public:
|
|||||||
});
|
});
|
||||||
|
|
||||||
// fragmented message
|
// fragmented message
|
||||||
doTest(pmd, [&](ws_type& ws)
|
doTest<deflateSupported>(pmd,
|
||||||
|
[&](ws_type_t<deflateSupported>& ws)
|
||||||
{
|
{
|
||||||
ws.auto_fragment(false);
|
ws.auto_fragment(false);
|
||||||
ws.binary(false);
|
ws.binary(false);
|
||||||
@ -88,7 +91,8 @@ public:
|
|||||||
});
|
});
|
||||||
|
|
||||||
// continuation
|
// continuation
|
||||||
doTest(pmd, [&](ws_type& ws)
|
doTest<deflateSupported>(pmd,
|
||||||
|
[&](ws_type_t<deflateSupported>& ws)
|
||||||
{
|
{
|
||||||
std::string const s = "Hello";
|
std::string const s = "Hello";
|
||||||
std::size_t const chop = 3;
|
std::size_t const chop = 3;
|
||||||
@ -103,7 +107,8 @@ public:
|
|||||||
});
|
});
|
||||||
|
|
||||||
// mask
|
// mask
|
||||||
doTest(pmd, [&](ws_type& ws)
|
doTest<deflateSupported>(pmd,
|
||||||
|
[&](ws_type_t<deflateSupported>& ws)
|
||||||
{
|
{
|
||||||
ws.auto_fragment(false);
|
ws.auto_fragment(false);
|
||||||
std::string const s = "Hello";
|
std::string const s = "Hello";
|
||||||
@ -114,7 +119,8 @@ public:
|
|||||||
});
|
});
|
||||||
|
|
||||||
// mask (large)
|
// mask (large)
|
||||||
doTest(pmd, [&](ws_type& ws)
|
doTest<deflateSupported>(pmd,
|
||||||
|
[&](ws_type_t<deflateSupported>& ws)
|
||||||
{
|
{
|
||||||
ws.auto_fragment(false);
|
ws.auto_fragment(false);
|
||||||
ws.write_buffer_size(16);
|
ws.write_buffer_size(16);
|
||||||
@ -126,7 +132,8 @@ public:
|
|||||||
});
|
});
|
||||||
|
|
||||||
// mask, autofrag
|
// mask, autofrag
|
||||||
doTest(pmd, [&](ws_type& ws)
|
doTest<deflateSupported>(pmd,
|
||||||
|
[&](ws_type_t<deflateSupported>& ws)
|
||||||
{
|
{
|
||||||
ws.auto_fragment(true);
|
ws.auto_fragment(true);
|
||||||
std::string const s(16384, '*');
|
std::string const s(16384, '*');
|
||||||
@ -140,7 +147,7 @@ public:
|
|||||||
doStreamLoop([&](test::stream& ts)
|
doStreamLoop([&](test::stream& ts)
|
||||||
{
|
{
|
||||||
echo_server es{log, kind::async_client};
|
echo_server es{log, kind::async_client};
|
||||||
ws_type ws{ts};
|
ws_type_t<deflateSupported> ws{ts};
|
||||||
ws.next_layer().connect(es.stream());
|
ws.next_layer().connect(es.stream());
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -166,7 +173,7 @@ public:
|
|||||||
doStreamLoop([&](test::stream& ts)
|
doStreamLoop([&](test::stream& ts)
|
||||||
{
|
{
|
||||||
echo_server es{log, kind::async_client};
|
echo_server es{log, kind::async_client};
|
||||||
ws_type ws{ts};
|
ws_type_t<deflateSupported> ws{ts};
|
||||||
ws.next_layer().connect(es.stream());
|
ws.next_layer().connect(es.stream());
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -187,7 +194,15 @@ public:
|
|||||||
}
|
}
|
||||||
ts.close();
|
ts.close();
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Wrap>
|
||||||
|
void
|
||||||
|
doTestWriteDeflate(Wrap const& w)
|
||||||
|
{
|
||||||
|
using boost::asio::buffer;
|
||||||
|
|
||||||
|
permessage_deflate pmd;
|
||||||
pmd.client_enable = true;
|
pmd.client_enable = true;
|
||||||
pmd.server_enable = true;
|
pmd.server_enable = true;
|
||||||
pmd.compLevel = 1;
|
pmd.compLevel = 1;
|
||||||
@ -238,11 +253,15 @@ public:
|
|||||||
{
|
{
|
||||||
using boost::asio::buffer;
|
using boost::asio::buffer;
|
||||||
|
|
||||||
doTestWrite(SyncClient{});
|
doTestWrite<false>(SyncClient{});
|
||||||
|
doTestWrite<true>(SyncClient{});
|
||||||
|
doTestWriteDeflate(SyncClient{});
|
||||||
|
|
||||||
yield_to([&](yield_context yield)
|
yield_to([&](yield_context yield)
|
||||||
{
|
{
|
||||||
doTestWrite(AsyncClient{yield});
|
doTestWrite<false>(AsyncClient{yield});
|
||||||
|
doTestWrite<true>(AsyncClient{yield});
|
||||||
|
doTestWriteDeflate(AsyncClient{yield});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ boost::asio::ip::tcp::socket sock{ioc};
|
|||||||
|
|
||||||
{
|
{
|
||||||
//[ws_snippet_6
|
//[ws_snippet_6
|
||||||
std::string const host = "mywebapp.com";
|
std::string const host = "example.com";
|
||||||
boost::asio::ip::tcp::resolver r{ioc};
|
boost::asio::ip::tcp::resolver r{ioc};
|
||||||
stream<boost::asio::ip::tcp::socket> ws{ioc};
|
stream<boost::asio::ip::tcp::socket> ws{ioc};
|
||||||
auto const results = r.resolve(host, "ws");
|
auto const results = r.resolve(host, "ws");
|
||||||
@ -310,6 +310,16 @@ struct custom_wrapper
|
|||||||
|
|
||||||
//]
|
//]
|
||||||
|
|
||||||
|
//[ws_snippet_26
|
||||||
|
|
||||||
|
// A WebSocket stream
|
||||||
|
template<
|
||||||
|
class NextLayer,
|
||||||
|
bool deflateSupported = true>
|
||||||
|
class stream;
|
||||||
|
|
||||||
|
//]
|
||||||
|
|
||||||
} // doc_ws_snippets
|
} // doc_ws_snippets
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
Reference in New Issue
Block a user