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:
Vinnie Falco
2017-06-08 17:36:31 -07:00
parent 669b1feae1
commit f22895224b
9 changed files with 99 additions and 230 deletions

View File

@ -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

View File

@ -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>

View File

@ -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();
}

View File

@ -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);

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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});
//]

View File

@ -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