From f22895224b7983f69ffaa60e8315567d03c90711 Mon Sep 17 00:00:00 2001 From: Vinnie Falco Date: Thu, 8 Jun 2017 17:36:31 -0700 Subject: [PATCH] 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. --- CHANGELOG.md | 13 +++ doc/quickref.xml | 1 - examples/websocket_async_echo_server.hpp | 101 +++-------------------- examples/websocket_echo.cpp | 31 +++++-- examples/websocket_sync_echo_server.hpp | 94 ++------------------- include/beast/websocket/option.hpp | 37 --------- include/beast/websocket/stream.hpp | 42 ++++++++-- test/websocket/doc_snippets.cpp | 2 +- test/websocket/stream.cpp | 8 +- 9 files changed, 99 insertions(+), 230 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 55a85aa7..ae233471 100644 --- a/CHANGELOG.md +++ b/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 diff --git a/doc/quickref.xml b/doc/quickref.xml index 45362956..2622cbb4 100644 --- a/doc/quickref.xml +++ b/doc/quickref.xml @@ -123,7 +123,6 @@ Options - auto_fragment message_type permessage_deflate ping_callback diff --git a/examples/websocket_async_echo_server.hpp b/examples/websocket_async_echo_server.hpp index 75d7ddad..4b4f1369 100644 --- a/examples/websocket_async_echo_server.hpp +++ b/examples/websocket_async_echo_server.hpp @@ -20,8 +20,6 @@ #include #include #include -#include -#include #include 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 options_set - { - // workaround for std::function bug in msvc - struct callable - { - virtual ~callable() = default; - virtual void operator()( - beast::websocket::stream&) = 0; - }; - - template - class callable_impl : public callable - { - T t_; - - public: - template - callable_impl(U&& u) - : t_(std::forward(u)) - { - } - - void - operator()(beast::websocket::stream& ws) - { - t_(ws); - } - }; - - template - class lambda - { - Opt opt_; - - public: - lambda(lambda&&) = default; - lambda(lambda const&) = default; - - lambda(Opt const& opt) - : opt_(opt) - { - } - - void - operator()(beast::websocket::stream& ws) const - { - ws.set_option(opt_); - } - }; - - std::unordered_map> list_; - - public: - template - void - set_option(Opt const& opt) - { - std::unique_ptr p; - p.reset(new callable_impl>{opt}); - list_[std::type_index{ - typeid(Opt)}] = std::move(p); - } - - void - set_options(beast::websocket::stream& 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 thread_; boost::optional work_; - options_set opts_; + std::function&)> 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 + template 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)...)) { auto& d = *d_; - d.server.opts_.set_options(d.ws); + d.server.mod_(d.ws); run(); } diff --git a/examples/websocket_echo.cpp b/examples/websocket_echo.cpp index e8171526..524d83d3 100644 --- a/examples/websocket_echo.cpp +++ b/examples/websocket_echo.cpp @@ -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 + void + operator()(beast::websocket::stream& 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); diff --git a/examples/websocket_sync_echo_server.hpp b/examples/websocket_sync_echo_server.hpp index 3df6ddb5..a4fd09e8 100644 --- a/examples/websocket_sync_echo_server.hpp +++ b/examples/websocket_sync_echo_server.hpp @@ -20,8 +20,6 @@ #include #include #include -#include -#include #include 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 options_set - { - // workaround for std::function bug in msvc - struct callable - { - virtual ~callable() = default; - virtual void operator()( - beast::websocket::stream&) = 0; - }; - - template - class callable_impl : public callable - { - T t_; - - public: - template - callable_impl(U&& u) - : t_(std::forward(u)) - { - } - - void - operator()(beast::websocket::stream& ws) - { - t_(ws); - } - }; - - template - class lambda - { - Opt opt_; - - public: - lambda(lambda&&) = default; - lambda(lambda const&) = default; - - lambda(Opt const& opt) - : opt_(opt) - { - } - - void - operator()(beast::websocket::stream& ws) const - { - ws.set_option(opt_); - } - }; - - std::unordered_map> list_; - - public: - template - void - set_option(Opt const& opt) - { - std::unique_ptr p; - p.reset(new callable_impl>{opt}); - list_[std::type_index{ - typeid(Opt)}] = std::move(p); - } - - void - set_options(beast::websocket::stream& 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 opts_; + std::function&)> 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 + template 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) diff --git a/include/beast/websocket/option.hpp b/include/beast/websocket/option.hpp index ef6608e1..c5a0b7cc 100644 --- a/include/beast/websocket/option.hpp +++ b/include/beast/websocket/option.hpp @@ -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 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 diff --git a/include/beast/websocket/stream.hpp b/include/beast/websocket/stream.hpp index dd0f20aa..c114cda1 100644 --- a/include/beast/websocket/stream.hpp +++ b/include/beast/websocket/stream.hpp @@ -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 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)...); } - /// 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) diff --git a/test/websocket/doc_snippets.cpp b/test/websocket/doc_snippets.cpp index 4e7a7a30..55a6d66f 100644 --- a/test/websocket/doc_snippets.cpp +++ b/test/websocket/doc_snippets.cpp @@ -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}); //] diff --git a/test/websocket/stream.cpp b/test/websocket/stream.cpp index 69f7cde3..a2c23598 100644 --- a/test/websocket/stream.cpp +++ b/test/websocket/stream.cpp @@ -553,7 +553,7 @@ public: testOptions() { stream 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