mirror of
https://github.com/boostorg/beast.git
synced 2025-07-29 20:37:31 +02:00
auto_fragment is a member of stream (API Change):
fix #374, fix #446 * auto_fragment option struct is removed Actions Required: * Change call sites which use auto_fragment with set_option to call stream::auto_fragment instead.
This commit is contained in:
13
CHANGELOG.md
13
CHANGELOG.md
@ -1,3 +1,16 @@
|
||||
Version 52:
|
||||
|
||||
API Changes:
|
||||
|
||||
* auto_fragment is a member of stream
|
||||
|
||||
Actions Required:
|
||||
|
||||
* Change call sites which use auto_fragment with set_option
|
||||
to call stream::auto_fragment instead.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Version 51
|
||||
|
||||
* Fix operator<< for header
|
||||
|
@ -123,7 +123,6 @@
|
||||
</simplelist>
|
||||
<bridgehead renderas="sect3">Options</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member><link linkend="beast.ref.websocket__auto_fragment">auto_fragment</link></member>
|
||||
<member><link linkend="beast.ref.websocket__message_type">message_type</link></member>
|
||||
<member><link linkend="beast.ref.websocket__permessage_deflate">permessage_deflate</link></member>
|
||||
<member><link linkend="beast.ref.websocket__ping_callback">ping_callback</link></member>
|
||||
|
@ -20,8 +20,6 @@
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <type_traits>
|
||||
#include <typeindex>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
|
||||
namespace websocket {
|
||||
@ -37,81 +35,6 @@ public:
|
||||
using endpoint_type = boost::asio::ip::tcp::endpoint;
|
||||
|
||||
private:
|
||||
/** A container of type-erased option setters.
|
||||
*/
|
||||
template<class NextLayer>
|
||||
class options_set
|
||||
{
|
||||
// workaround for std::function bug in msvc
|
||||
struct callable
|
||||
{
|
||||
virtual ~callable() = default;
|
||||
virtual void operator()(
|
||||
beast::websocket::stream<NextLayer>&) = 0;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class callable_impl : public callable
|
||||
{
|
||||
T t_;
|
||||
|
||||
public:
|
||||
template<class U>
|
||||
callable_impl(U&& u)
|
||||
: t_(std::forward<U>(u))
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
operator()(beast::websocket::stream<NextLayer>& ws)
|
||||
{
|
||||
t_(ws);
|
||||
}
|
||||
};
|
||||
|
||||
template<class Opt>
|
||||
class lambda
|
||||
{
|
||||
Opt opt_;
|
||||
|
||||
public:
|
||||
lambda(lambda&&) = default;
|
||||
lambda(lambda const&) = default;
|
||||
|
||||
lambda(Opt const& opt)
|
||||
: opt_(opt)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
operator()(beast::websocket::stream<NextLayer>& ws) const
|
||||
{
|
||||
ws.set_option(opt_);
|
||||
}
|
||||
};
|
||||
|
||||
std::unordered_map<std::type_index,
|
||||
std::unique_ptr<callable>> list_;
|
||||
|
||||
public:
|
||||
template<class Opt>
|
||||
void
|
||||
set_option(Opt const& opt)
|
||||
{
|
||||
std::unique_ptr<callable> p;
|
||||
p.reset(new callable_impl<lambda<Opt>>{opt});
|
||||
list_[std::type_index{
|
||||
typeid(Opt)}] = std::move(p);
|
||||
}
|
||||
|
||||
void
|
||||
set_options(beast::websocket::stream<NextLayer>& ws)
|
||||
{
|
||||
for(auto const& op : list_)
|
||||
(*op.second)(ws);
|
||||
}
|
||||
};
|
||||
|
||||
std::ostream* log_;
|
||||
boost::asio::io_service ios_;
|
||||
socket_type sock_;
|
||||
@ -119,7 +42,7 @@ private:
|
||||
boost::asio::ip::tcp::acceptor acceptor_;
|
||||
std::vector<std::thread> thread_;
|
||||
boost::optional<boost::asio::io_service::work> work_;
|
||||
options_set<socket_type> opts_;
|
||||
std::function<void(beast::websocket::stream<socket_type>&)> mod_;
|
||||
|
||||
public:
|
||||
async_echo_server(async_echo_server const&) = delete;
|
||||
@ -150,9 +73,12 @@ public:
|
||||
~async_echo_server()
|
||||
{
|
||||
work_ = boost::none;
|
||||
error_code ec;
|
||||
ios_.dispatch(
|
||||
[&]{ acceptor_.close(ec); });
|
||||
[&]
|
||||
{
|
||||
error_code ec;
|
||||
acceptor_.close(ec);
|
||||
});
|
||||
for(auto& t : thread_)
|
||||
t.join();
|
||||
}
|
||||
@ -165,17 +91,16 @@ public:
|
||||
return acceptor_.local_endpoint();
|
||||
}
|
||||
|
||||
/** Set a websocket option.
|
||||
/** Set a handler called for new streams.
|
||||
|
||||
The option will be applied to all new connections.
|
||||
|
||||
@param opt The option to apply.
|
||||
This function is called for each new stream.
|
||||
It is used to set options for every connection.
|
||||
*/
|
||||
template<class Opt>
|
||||
template<class F>
|
||||
void
|
||||
set_option(Opt const& opt)
|
||||
on_new_stream(F const& f)
|
||||
{
|
||||
opts_.set_option(opt);
|
||||
mod_ = f;
|
||||
}
|
||||
|
||||
/** Open a listening port.
|
||||
@ -253,7 +178,7 @@ private:
|
||||
std::forward<Args>(args)...))
|
||||
{
|
||||
auto& d = *d_;
|
||||
d.server.opts_.set_options(d.ws);
|
||||
d.server.mod_(d.ws);
|
||||
run();
|
||||
}
|
||||
|
||||
|
@ -25,6 +25,29 @@ sig_wait()
|
||||
ios.run();
|
||||
}
|
||||
|
||||
class set_stream_options
|
||||
{
|
||||
beast::websocket::permessage_deflate pmd_;
|
||||
|
||||
public:
|
||||
set_stream_options(set_stream_options const&) = default;
|
||||
|
||||
set_stream_options(
|
||||
beast::websocket::permessage_deflate const& pmd)
|
||||
: pmd_(pmd)
|
||||
{
|
||||
}
|
||||
|
||||
template<class NextLayer>
|
||||
void
|
||||
operator()(beast::websocket::stream<NextLayer>& ws) const
|
||||
{
|
||||
ws.auto_fragment(false);
|
||||
ws.set_option(pmd_);
|
||||
ws.set_option(beast::websocket::read_message_max{64 * 1024 * 1024});
|
||||
}
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace beast::websocket;
|
||||
@ -39,16 +62,12 @@ int main()
|
||||
pmd.compLevel = 3;
|
||||
|
||||
websocket::async_echo_server s1{&std::cout, 1};
|
||||
s1.set_option(read_message_max{64 * 1024 * 1024});
|
||||
s1.set_option(auto_fragment{false});
|
||||
s1.set_option(pmd);
|
||||
s1.on_new_stream(set_stream_options{pmd});
|
||||
s1.open(endpoint_type{
|
||||
address_type::from_string("127.0.0.1"), 6000 }, ec);
|
||||
|
||||
websocket::sync_echo_server s2{&std::cout};
|
||||
s2.set_option(read_message_max{64 * 1024 * 1024});
|
||||
s2.set_option(auto_fragment{false});
|
||||
s2.set_option(pmd);
|
||||
s2.on_new_stream(set_stream_options{pmd});
|
||||
s2.open(endpoint_type{
|
||||
address_type::from_string("127.0.0.1"), 6001 }, ec);
|
||||
|
||||
|
@ -20,8 +20,6 @@
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <type_traits>
|
||||
#include <typeindex>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
|
||||
namespace websocket {
|
||||
@ -37,88 +35,13 @@ public:
|
||||
using socket_type = boost::asio::ip::tcp::socket;
|
||||
|
||||
private:
|
||||
/** A container of type-erased option setters.
|
||||
*/
|
||||
template<class NextLayer>
|
||||
class options_set
|
||||
{
|
||||
// workaround for std::function bug in msvc
|
||||
struct callable
|
||||
{
|
||||
virtual ~callable() = default;
|
||||
virtual void operator()(
|
||||
beast::websocket::stream<NextLayer>&) = 0;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class callable_impl : public callable
|
||||
{
|
||||
T t_;
|
||||
|
||||
public:
|
||||
template<class U>
|
||||
callable_impl(U&& u)
|
||||
: t_(std::forward<U>(u))
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
operator()(beast::websocket::stream<NextLayer>& ws)
|
||||
{
|
||||
t_(ws);
|
||||
}
|
||||
};
|
||||
|
||||
template<class Opt>
|
||||
class lambda
|
||||
{
|
||||
Opt opt_;
|
||||
|
||||
public:
|
||||
lambda(lambda&&) = default;
|
||||
lambda(lambda const&) = default;
|
||||
|
||||
lambda(Opt const& opt)
|
||||
: opt_(opt)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
operator()(beast::websocket::stream<NextLayer>& ws) const
|
||||
{
|
||||
ws.set_option(opt_);
|
||||
}
|
||||
};
|
||||
|
||||
std::unordered_map<std::type_index,
|
||||
std::unique_ptr<callable>> list_;
|
||||
|
||||
public:
|
||||
template<class Opt>
|
||||
void
|
||||
set_option(Opt const& opt)
|
||||
{
|
||||
std::unique_ptr<callable> p;
|
||||
p.reset(new callable_impl<lambda<Opt>>{opt});
|
||||
list_[std::type_index{
|
||||
typeid(Opt)}] = std::move(p);
|
||||
}
|
||||
|
||||
void
|
||||
set_options(beast::websocket::stream<NextLayer>& ws)
|
||||
{
|
||||
for(auto const& op : list_)
|
||||
(*op.second)(ws);
|
||||
}
|
||||
};
|
||||
|
||||
std::ostream* log_;
|
||||
boost::asio::io_service ios_;
|
||||
socket_type sock_;
|
||||
endpoint_type ep_;
|
||||
boost::asio::ip::tcp::acceptor acceptor_;
|
||||
std::thread thread_;
|
||||
options_set<socket_type> opts_;
|
||||
std::function<void(beast::websocket::stream<socket_type>&)> mod_;
|
||||
|
||||
public:
|
||||
/** Constructor.
|
||||
@ -154,17 +77,16 @@ public:
|
||||
return acceptor_.local_endpoint();
|
||||
}
|
||||
|
||||
/** Set a websocket option.
|
||||
/** Set a handler called for new streams.
|
||||
|
||||
The option will be applied to all new connections.
|
||||
|
||||
@param opt The option to apply.
|
||||
This function is called for each new stream.
|
||||
It is used to set options for every connection.
|
||||
*/
|
||||
template<class Opt>
|
||||
template<class F>
|
||||
void
|
||||
set_option(Opt const& opt)
|
||||
on_new_stream(F const& f)
|
||||
{
|
||||
opts_.set_option(opt);
|
||||
mod_ = f;
|
||||
}
|
||||
|
||||
/** Open a listening port.
|
||||
@ -269,7 +191,7 @@ private:
|
||||
using boost::asio::buffer_copy;
|
||||
beast::websocket::stream<
|
||||
socket_type> ws{std::move(sock)};
|
||||
opts_.set_options(ws);
|
||||
mod_(ws);
|
||||
error_code ec;
|
||||
ws.accept_ex(
|
||||
[](beast::websocket::response_type& res)
|
||||
|
@ -22,43 +22,6 @@
|
||||
namespace beast {
|
||||
namespace websocket {
|
||||
|
||||
/** Automatic fragmentation option.
|
||||
|
||||
Determines if outgoing message payloads are broken up into
|
||||
multiple pieces.
|
||||
|
||||
When the automatic fragmentation size is turned on, outgoing
|
||||
message payloads are broken up into multiple frames no larger
|
||||
than the write buffer size.
|
||||
|
||||
The default setting is to fragment messages.
|
||||
|
||||
@note Objects of this type are used with
|
||||
@ref beast::websocket::stream::set_option.
|
||||
|
||||
@par Example
|
||||
Setting the automatic fragmentation option:
|
||||
@code
|
||||
...
|
||||
websocket::stream<ip::tcp::socket> stream(ios);
|
||||
stream.set_option(auto_fragment{true});
|
||||
@endcode
|
||||
*/
|
||||
#if BEAST_DOXYGEN
|
||||
using auto_fragment = implementation_defined;
|
||||
#else
|
||||
struct auto_fragment
|
||||
{
|
||||
bool value;
|
||||
|
||||
explicit
|
||||
auto_fragment(bool v)
|
||||
: value(v)
|
||||
{
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
/** Message type option.
|
||||
|
||||
This controls the opcode set for outgoing messages. Valid
|
||||
|
@ -151,6 +151,41 @@ public:
|
||||
*/
|
||||
~stream() = default;
|
||||
|
||||
/** Set the automatic fragmentation option.
|
||||
|
||||
Determines if outgoing message payloads are broken up into
|
||||
multiple pieces.
|
||||
|
||||
When the automatic fragmentation size is turned on, outgoing
|
||||
message payloads are broken up into multiple frames no larger
|
||||
than the write buffer size.
|
||||
|
||||
The default setting is to fragment messages.
|
||||
|
||||
@note Objects of this type are used with
|
||||
@ref beast::websocket::stream::set_option.
|
||||
|
||||
@par Example
|
||||
Setting the automatic fragmentation option:
|
||||
@code
|
||||
...
|
||||
websocket::stream<ip::tcp::socket> stream{ios};
|
||||
stream.auto_fragment(true);
|
||||
@endcode
|
||||
*/
|
||||
void
|
||||
auto_fragment(bool v)
|
||||
{
|
||||
wr_autofrag_ = v;
|
||||
}
|
||||
|
||||
/// Returns `true` if the automatic fragmentation option is set.
|
||||
bool
|
||||
auto_fragment() const
|
||||
{
|
||||
return wr_autofrag_;
|
||||
}
|
||||
|
||||
/** Set options on the stream.
|
||||
|
||||
The application must ensure that calls to set options
|
||||
@ -173,13 +208,6 @@ public:
|
||||
std::forward<An>(an)...);
|
||||
}
|
||||
|
||||
/// Set the automatic fragment size option
|
||||
void
|
||||
set_option(auto_fragment const& o)
|
||||
{
|
||||
wr_autofrag_ = o.value;
|
||||
}
|
||||
|
||||
/// Set the outgoing message type
|
||||
void
|
||||
set_option(message_type const& o)
|
||||
|
@ -205,7 +205,7 @@ boost::asio::ip::tcp::socket sock{ios};
|
||||
//]
|
||||
|
||||
//[ws_snippet_19
|
||||
ws.set_option(auto_fragment{true});
|
||||
ws.auto_fragment(true);
|
||||
ws.set_option(write_buffer_size{16384});
|
||||
//]
|
||||
|
||||
|
@ -553,7 +553,7 @@ public:
|
||||
testOptions()
|
||||
{
|
||||
stream<socket_type> ws(ios_);
|
||||
ws.set_option(auto_fragment{true});
|
||||
ws.auto_fragment(true);
|
||||
ws.set_option(write_buffer_size{2048});
|
||||
ws.set_option(message_type{opcode::text});
|
||||
ws.set_option(read_buffer_size{8192});
|
||||
@ -1655,7 +1655,7 @@ public:
|
||||
c.handshake(ws, "localhost", "/");
|
||||
|
||||
// send message
|
||||
ws.set_option(auto_fragment{false});
|
||||
ws.auto_fragment(false);
|
||||
ws.set_option(message_type(opcode::text));
|
||||
c.write(ws, sbuf("Hello"));
|
||||
{
|
||||
@ -1728,7 +1728,7 @@ public:
|
||||
c.pong(ws, "");
|
||||
|
||||
// send auto fragmented message
|
||||
ws.set_option(auto_fragment{true});
|
||||
ws.auto_fragment(true);
|
||||
ws.set_option(write_buffer_size{8});
|
||||
c.write(ws, sbuf("Now is the time for all good men"));
|
||||
{
|
||||
@ -1738,7 +1738,7 @@ public:
|
||||
c.read(ws, op, b);
|
||||
BEAST_EXPECT(to_string(b.data()) == "Now is the time for all good men");
|
||||
}
|
||||
ws.set_option(auto_fragment{false});
|
||||
ws.auto_fragment(false);
|
||||
ws.set_option(write_buffer_size{4096});
|
||||
|
||||
// send message with write buffer limit
|
||||
|
Reference in New Issue
Block a user