diff --git a/CHANGELOG.md b/CHANGELOG.md index e088a4a1..8b166b19 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ API Changes: * read_message_max is a member of stream * write_buffer_size is a member of stream * ping_callback is a member of stream +* Remove opcode from read, async_read Actions Required: @@ -29,6 +30,10 @@ Actions Required: * Change call sites which use ping_callback with set_option to call stream::ping_callback instead. +* Remove the `opcode` reference parameter from calls to synchronous + and asynchronous read functions, replace the logic with calls to + stream::got_binary and stream::got_text instead. + -------------------------------------------------------------------------------- Version 51 diff --git a/examples/ssl/websocket_ssl_example.cpp b/examples/ssl/websocket_ssl_example.cpp index 466758c9..f3427d6e 100644 --- a/examples/ssl/websocket_ssl_example.cpp +++ b/examples/ssl/websocket_ssl_example.cpp @@ -42,8 +42,6 @@ int main() // Receive Secure WebSocket message, print and close using Beast beast::multi_buffer b; - beast::websocket::opcode op; - ws.read(op, b); ws.close(beast::websocket::close_code::normal); std::cout << beast::buffers(b.data()) << "\n"; } diff --git a/examples/websocket_async_echo_server.hpp b/examples/websocket_async_echo_server.hpp index e87f94da..9bccbe06 100644 --- a/examples/websocket_async_echo_server.hpp +++ b/examples/websocket_async_echo_server.hpp @@ -139,7 +139,6 @@ private: int state = 0; beast::websocket::stream ws; boost::asio::io_service::strand strand; - beast::websocket::opcode op; beast::multi_buffer db; std::size_t id; @@ -218,7 +217,7 @@ private: d.db.consume(d.db.size()); // read message d.state = 2; - d.ws.async_read(d.op, d.db, + d.ws.async_read(d.db, d.strand.wrap(std::move(*this))); return; @@ -230,7 +229,7 @@ private: return fail("async_read", ec); // write message d.state = 1; - d.ws.binary(d.op == beast::websocket::opcode::binary); + d.ws.binary(d.ws.got_binary()); d.ws.async_write(d.db.data(), d.strand.wrap(std::move(*this))); return; diff --git a/examples/websocket_example.cpp b/examples/websocket_example.cpp index 72093d60..69e6df8b 100644 --- a/examples/websocket_example.cpp +++ b/examples/websocket_example.cpp @@ -30,8 +30,7 @@ int main() // Receive WebSocket message, print and close using beast beast::multi_buffer b; - beast::websocket::opcode op; - ws.read(op, b); + ws.read(b); ws.close(beast::websocket::close_code::normal); std::cout << beast::buffers(b.data()) << "\n"; } diff --git a/examples/websocket_sync_echo_server.hpp b/examples/websocket_sync_echo_server.hpp index fc6dc2c0..369cc16a 100644 --- a/examples/websocket_sync_echo_server.hpp +++ b/examples/websocket_sync_echo_server.hpp @@ -207,15 +207,14 @@ private: } for(;;) { - beast::websocket::opcode op; beast::multi_buffer b; - ws.read(op, b, ec); + ws.read(b, ec); if(ec) { auto const s = ec.message(); break; } - ws.binary(op == beast::websocket::opcode::binary); + ws.binary(ws.got_binary()); ws.write(b.data(), ec); if(ec) break; diff --git a/include/beast/websocket/impl/read.ipp b/include/beast/websocket/impl/read.ipp index eba9bab4..399ffdd8 100644 --- a/include/beast/websocket/impl/read.ipp +++ b/include/beast/websocket/impl/read.ipp @@ -1001,16 +1001,13 @@ class stream::read_op { bool cont; stream& ws; - opcode& op; DynamicBuffer& db; frame_info fi; int state = 0; - data(Handler& handler, - stream& ws_, opcode& op_, + data(Handler& handler, stream& ws_, DynamicBuffer& sb_) : ws(ws_) - , op(op_) , db(sb_) { using boost::asio::asio_handler_is_continuation; @@ -1091,7 +1088,6 @@ operator()(error_code const& ec, bool again) // got payload case 1: - d.op = d.fi.op; if(d.fi.fin) goto upcall; d.state = 0; @@ -1107,8 +1103,7 @@ template async_return_type< ReadHandler, void(error_code)> stream:: -async_read(opcode& op, - DynamicBuffer& buffer, ReadHandler&& handler) +async_read(DynamicBuffer& buffer, ReadHandler&& handler) { static_assert(is_async_stream::value, "AsyncStream requirements requirements not met"); @@ -1117,8 +1112,8 @@ async_read(opcode& op, async_completion init{handler}; read_op>{init.completion_handler, - *this, op, buffer}; + ReadHandler, void(error_code)>>{ + init.completion_handler, *this, buffer}; return init.result.get(); } @@ -1126,14 +1121,14 @@ template template void stream:: -read(opcode& op, DynamicBuffer& buffer) +read(DynamicBuffer& buffer) { static_assert(is_sync_stream::value, "SyncStream requirements not met"); static_assert(beast::is_dynamic_buffer::value, "DynamicBuffer requirements not met"); error_code ec; - read(op, buffer, ec); + read(buffer, ec); if(ec) BOOST_THROW_EXCEPTION(system_error{ec}); } @@ -1142,7 +1137,7 @@ template template void stream:: -read(opcode& op, DynamicBuffer& buffer, error_code& ec) +read(DynamicBuffer& buffer, error_code& ec) { static_assert(is_sync_stream::value, "SyncStream requirements not met"); @@ -1154,7 +1149,6 @@ read(opcode& op, DynamicBuffer& buffer, error_code& ec) read_frame(fi, buffer, ec); if(ec) break; - op = fi.op; if(fi.fin) break; } diff --git a/include/beast/websocket/stream.hpp b/include/beast/websocket/stream.hpp index 12bd3810..bc17971a 100644 --- a/include/beast/websocket/stream.hpp +++ b/include/beast/websocket/stream.hpp @@ -75,8 +75,8 @@ struct frame_info @endcode Alternatively, you can write: @code - ip::tcp::socket sock(io_service); - websocket::stream ws(sock); + ip::tcp::socket sock{io_service}; + websocket::stream ws{sock}; @endcode @tparam NextLayer The type representing the next layer, to which @@ -223,28 +223,6 @@ public: return stream_.lowest_layer(); } - /** Set options on the stream. - - The application must ensure that calls to set options - are performed within the same implicit or explicit strand. - - @param args One or more stream options to set. - */ -#if BEAST_DOXYGEN - template - void - set_option(Args&&... args) -#else - template - void - set_option(A1&& a1, A2&& a2, An&&... an) -#endif - { - set_option(std::forward(a1)); - set_option(std::forward(a2), - std::forward(an)...); - } - /// Set the permessage-deflate extension options void set_option(permessage_deflate const& o); @@ -469,6 +447,38 @@ public: return wr_buf_size_; } + /** Set the text message option. + + This controls whether or not outgoing message opcodes + are set to binary or text. The setting is only applied + at the start when a caller begins a new message. Changing + the opcode after a message is started will only take effect + after the current message being sent is complete. + + The default setting is to send text messages. + + @param v `true` if outgoing messages should indicate + text, or `false` if they should indicate binary. + + @par Example + Setting the message type to text. + @code + ws.text(true); + @endcode + */ + void + text(bool v) + { + wr_opcode_ = v ? opcode::text : opcode::binary; + } + + /// Returns `true` if the text message option is set. + bool + text() const + { + return wr_opcode_ == opcode::text; + } + /** Returns the close reason received from the peer. This is only valid after a read completes with error::closed. @@ -479,6 +489,36 @@ public: return cr_; } + /** Returns `true` if the latest message data indicates binary. + + This function informs the caller of whether the last + received message frame represents a message with the + binary opcode. + + If there is no last message frame, the return value is + undefined. + */ + bool + got_binary() + { + return rd_.op == opcode::binary; + } + + /** Returns `true` if the latest message data indicates text. + + This function informs the caller of whether the last + received message frame represents a message with the + text opcode. + + If there is no last message frame, the return value is + undefined. + */ + bool + got_text() + { + return ! got_binary(); + } + /** Read and respond to a WebSocket HTTP Upgrade request. This function is used to synchronously read an HTTP WebSocket @@ -1638,8 +1678,7 @@ public: @endcode */ void - handshake(string_view host, - string_view target); + handshake(string_view host, string_view target); /** Send an HTTP WebSocket Upgrade request and receive the response. @@ -1686,8 +1725,7 @@ public: */ void handshake(response_type& res, - string_view host, - string_view target); + string_view host, string_view target); /** Send an HTTP WebSocket Upgrade request and receive the response. @@ -1743,9 +1781,8 @@ public: */ template void - handshake_ex(string_view host, - string_view target, - RequestDecorator const& decorator); + handshake_ex(string_view host, string_view target, + RequestDecorator const& decorator); /** Send an HTTP WebSocket Upgrade request and receive the response. @@ -1806,9 +1843,8 @@ public: template void handshake_ex(response_type& res, - string_view host, - string_view target, - RequestDecorator const& decorator); + string_view host, string_view target, + RequestDecorator const& decorator); /** Send an HTTP WebSocket Upgrade request and receive the response. @@ -1894,9 +1930,7 @@ public: */ void handshake(response_type& res, - string_view host, - string_view target, - error_code& ec); + string_view host, string_view target, error_code& ec); /** Send an HTTP WebSocket Upgrade request and receive the response. @@ -1952,9 +1986,8 @@ public: template void handshake_ex(string_view host, - string_view target, - RequestDecorator const& decorator, - error_code& ec); + string_view target, RequestDecorator const& decorator, + error_code& ec); /** Send an HTTP WebSocket Upgrade request and receive the response. @@ -2014,10 +2047,8 @@ public: template void handshake_ex(response_type& res, - string_view host, - string_view target, - RequestDecorator const& decorator, - error_code& ec); + string_view host, string_view target, + RequestDecorator const& decorator, error_code& ec); /** Start an asynchronous operation to send an upgrade request and receive the response. @@ -2067,8 +2098,7 @@ public: HandshakeHandler, void(error_code)> #endif async_handshake(string_view host, - string_view target, - HandshakeHandler&& handler); + string_view target, HandshakeHandler&& handler); /** Start an asynchronous operation to send an upgrade request and receive the response. @@ -2122,9 +2152,8 @@ public: HandshakeHandler, void(error_code)> #endif async_handshake(response_type& res, - string_view host, - string_view target, - HandshakeHandler&& handler); + string_view host, string_view target, + HandshakeHandler&& handler); /** Start an asynchronous operation to send an upgrade request and receive the response. @@ -2183,9 +2212,8 @@ public: HandshakeHandler, void(error_code)> #endif async_handshake_ex(string_view host, - string_view target, - RequestDecorator const& decorator, - HandshakeHandler&& handler); + string_view target, RequestDecorator const& decorator, + HandshakeHandler&& handler); /** Start an asynchronous operation to send an upgrade request and receive the response. @@ -2248,10 +2276,9 @@ public: HandshakeHandler, void(error_code)> #endif async_handshake_ex(response_type& res, - string_view host, - string_view target, - RequestDecorator const& decorator, - HandshakeHandler&& handler); + string_view host, string_view target, + RequestDecorator const& decorator, + HandshakeHandler&& handler); /** Send a WebSocket close frame. @@ -2580,7 +2607,7 @@ public: */ template void - read(opcode& op, DynamicBuffer& buffer); + read(DynamicBuffer& buffer); /** Read a message from the stream. @@ -2620,7 +2647,7 @@ public: */ template void - read(opcode& op, DynamicBuffer& buffer, error_code& ec); + read(DynamicBuffer& buffer, error_code& ec); /** Start an asynchronous operation to read a message from the stream. @@ -2688,7 +2715,7 @@ public: async_return_type< ReadHandler, void(error_code)> #endif - async_read(opcode& op, DynamicBuffer& buffer, ReadHandler&& handler); + async_read(DynamicBuffer& buffer, ReadHandler&& handler); /** Read a message frame from the stream. diff --git a/test/websocket/doc_snippets.cpp b/test/websocket/doc_snippets.cpp index dc3fe8a8..36a1de13 100644 --- a/test/websocket/doc_snippets.cpp +++ b/test/websocket/doc_snippets.cpp @@ -151,10 +151,9 @@ boost::asio::ip::tcp::socket sock{ios}; stream ws{ios}; //[ws_snippet_15 multi_buffer buffer; - opcode op; - ws.read(op, buffer); + ws.read(buffer); - ws.binary(op == opcode::binary); + ws.text(ws.got_text()); ws.write(buffer.data()); buffer.consume(buffer.size()); //] @@ -210,9 +209,8 @@ boost::asio::ip::tcp::socket sock{ios}; //] //[ws_snippet_20 - opcode op; multi_buffer buffer; - ws.async_read(op, buffer, + ws.async_read(buffer, [](error_code ec) { // Do something with the buffer @@ -226,8 +224,7 @@ boost::asio::ip::tcp::socket sock{ios}; void echo(stream& ws, multi_buffer& buffer, boost::asio::yield_context yield) { - opcode op; - ws.async_read(op, buffer, yield); + ws.async_read(buffer, yield); std::future fut = ws.async_write(buffer.data(), boost::asio::use_future); } diff --git a/test/websocket/ssl/ssl_server.cpp b/test/websocket/ssl/ssl_server.cpp index 7b3612c0..6dc3ed10 100644 --- a/test/websocket/ssl/ssl_server.cpp +++ b/test/websocket/ssl/ssl_server.cpp @@ -130,14 +130,13 @@ public: // Receive Secure WebSocket message, print and close using Beast beast::multi_buffer b; - beast::websocket::opcode op; - ws.read(op, b); + ws.read(b); ws.close(beast::websocket::close_code::normal); try { for(;;) { - ws.read(op, b); + ws.read(b); b.consume(b.size()); } } diff --git a/test/websocket/ssl/websocket_async_ssl_echo_server.hpp b/test/websocket/ssl/websocket_async_ssl_echo_server.hpp index 317e62c5..285f3172 100644 --- a/test/websocket/ssl/websocket_async_ssl_echo_server.hpp +++ b/test/websocket/ssl/websocket_async_ssl_echo_server.hpp @@ -243,7 +243,7 @@ private: return fail("async_write", ec); d.db.consume(d.db.size()); d.state = 4; - d.ws.async_read(d.op, d.db, + d.ws.async_read(d.db, d.strand.wrap(std::move(*this))); return; @@ -254,7 +254,7 @@ private: if(ec) return fail("async_read", ec); d.state = 3; - d.ws.binary(d.op == beast::websocket::opcode::binary); + d.ws.binary(d.ws.got_binary()); d.ws.async_write(d.db.data(), d.strand.wrap(std::move(*this))); return; diff --git a/test/websocket/stream.cpp b/test/websocket/stream.cpp index 49d29403..45747d7c 100644 --- a/test/websocket/stream.cpp +++ b/test/websocket/stream.cpp @@ -265,9 +265,9 @@ public: class NextLayer, class DynamicBuffer> void read(stream& ws, - opcode& op, DynamicBuffer& buffer) const + DynamicBuffer& buffer) const { - ws.read(op, buffer); + ws.read(buffer); } template< @@ -503,10 +503,10 @@ public: class NextLayer, class DynamicBuffer> void read(stream& ws, - opcode& op, DynamicBuffer& buffer) const + DynamicBuffer& buffer) const { error_code ec; - ws.async_read(op, buffer, yield_[ec]); + ws.async_read(buffer, yield_[ec]); if(ec) throw system_error{ec}; } @@ -741,9 +741,8 @@ public: cbuf(0x88, 0x82, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x17)); try { - opcode op; multi_buffer b; - c.read(ws, op, b); + c.read(ws, b); fail("success", __FILE__, __LINE__); } catch(system_error const& e) @@ -771,9 +770,8 @@ public: BEAST_EXPECT(called); try { - opcode op; multi_buffer b; - c.read(ws, op, b); + c.read(ws, b); fail("success", __FILE__, __LINE__); } catch(system_error const& e) @@ -799,9 +797,8 @@ public: c.accept(ws, req); try { - opcode op; multi_buffer b; - c.read(ws, op, b); + c.read(ws, b); fail("success", __FILE__, __LINE__); } catch(system_error const& e) @@ -828,9 +825,8 @@ public: cbuf(0x88, 0x82, 0xff, 0xff)); try { - opcode op; multi_buffer b; - c.read(ws, op, b); + c.read(ws, b); fail("success", __FILE__, __LINE__); } catch(system_error const& e) @@ -1193,9 +1189,8 @@ public: ws.write(boost::asio::buffer(v), ec); if(! BEAST_EXPECTS(! ec, ec.message())) break; - opcode op; multi_buffer db; - ws.read(op, db, ec); + ws.read(db, ec); if(! BEAST_EXPECTS(! ec, ec.message())) break; BEAST_EXPECT(to_string(db.data()) == @@ -1219,9 +1214,8 @@ public: ws.async_write(boost::asio::buffer(v), do_yield[ec]); if(! BEAST_EXPECTS(! ec, ec.message())) break; - opcode op; multi_buffer db; - ws.async_read(op, db, do_yield[ec]); + ws.async_read(db, do_yield[ec]); if(! BEAST_EXPECTS(! ec, ec.message())) break; BEAST_EXPECT(to_string(db.data()) == @@ -1284,10 +1278,9 @@ public: }); // Read - opcode op; multi_buffer db; ++count; - ws.async_read(op, db, + ws.async_read(db, [&](error_code ec) { --count; @@ -1340,12 +1333,11 @@ public: ws.binary(true); ws.write(buffer_cat(sbuf("TEXT"), cbuf(0x03, 0xea, 0xf0, 0x28, 0x8c, 0xbc))); - opcode op; multi_buffer db; std::size_t count = 0; // Read text message with bad utf8. // Causes a close to be sent, blocking writes. - ws.async_read(op, db, + ws.async_read(db, [&](error_code ec) { // Read should fail with protocol error @@ -1353,7 +1345,7 @@ public: BEAST_EXPECTS( ec == error::failed, ec.message()); // Reads after failure are aborted - ws.async_read(op, db, + ws.async_read(db, [&](error_code ec) { ++count; @@ -1408,12 +1400,11 @@ public: // Cause close to be received ws.binary(true); ws.write(sbuf("CLOSE")); - opcode op; multi_buffer db; std::size_t count = 0; // Read a close frame. // Sends a close frame, blocking writes. - ws.async_read(op, db, + ws.async_read(db, [&](error_code ec) { // Read should complete with error::closed @@ -1474,10 +1465,9 @@ public: // Cause close to be received ws.binary(true); ws.write(sbuf("CLOSE")); - opcode op; multi_buffer db; std::size_t count = 0; - ws.async_read(op, db, + ws.async_read(db, [&](error_code ec) { ++count; @@ -1525,9 +1515,8 @@ public: BEAST_EXPECT(! ec); }); }); - opcode op; multi_buffer db; - ws.async_read(op, db, + ws.async_read(db, [&](error_code ec) { BEAST_EXPECTS(ec == error::closed, ec.message()); @@ -1558,8 +1547,7 @@ public: ws.write_frame(false, sbuf("u")); ws.write_frame(true, sbuf("v")); multi_buffer b; - opcode op; - ws.read(op, b, ec); + ws.read(b, ec); if(! BEAST_EXPECTS(! ec, ec.message())) return; } @@ -1617,9 +1605,8 @@ public: { try { - opcode op; multi_buffer db; - c.read(ws, op, db); + c.read(ws, db); fail(); throw abort_test{}; } @@ -1651,10 +1638,9 @@ public: c.write(ws, sbuf("Hello")); { // receive echoed message - opcode op; multi_buffer db; - c.read(ws, op, db); - BEAST_EXPECT(op == opcode::text); + c.read(ws, db); + BEAST_EXPECT(ws.got_text()); BEAST_EXPECT(to_string(db.data()) == "Hello"); } @@ -1685,11 +1671,10 @@ public: c.write(ws, sbuf("Hello")); { // receive echoed message - opcode op; multi_buffer db; - c.read(ws, op, db); + c.read(ws, db); BEAST_EXPECT(pong == 1); - BEAST_EXPECT(op == opcode::binary); + BEAST_EXPECT(ws.got_binary()); BEAST_EXPECT(to_string(db.data()) == "Hello"); } ws.ping_callback({}); @@ -1707,9 +1692,8 @@ public: c.write_frame(ws, true, sbuf("World!")); { // receive echoed message - opcode op; multi_buffer db; - c.read(ws, op, db); + c.read(ws, db); BEAST_EXPECT(pong == 1); BEAST_EXPECT(to_string(db.data()) == "Hello, World!"); } @@ -1724,9 +1708,8 @@ public: c.write(ws, sbuf("Now is the time for all good men")); { // receive echoed message - opcode op; multi_buffer b; - c.read(ws, op, b); + c.read(ws, b); BEAST_EXPECT(to_string(b.data()) == "Now is the time for all good men"); } ws.auto_fragment(false); @@ -1739,9 +1722,8 @@ public: c.write(ws, buffer(s.data(), s.size())); { // receive echoed message - opcode op; multi_buffer db; - c.read(ws, op, db); + c.read(ws, db); BEAST_EXPECT(to_string(db.data()) == s); } } @@ -1753,10 +1735,9 @@ public: c.write(ws, sbuf("Hello")); { // receive echoed message - opcode op; multi_buffer db; - c.read(ws, op, db); - BEAST_EXPECT(op == opcode::text); + c.read(ws, db); + BEAST_EXPECT(ws.got_text()); BEAST_EXPECT(to_string(db.data()) == "Hello"); } diff --git a/test/websocket/websocket_async_echo_server.hpp b/test/websocket/websocket_async_echo_server.hpp index 74a9a169..d33193e2 100644 --- a/test/websocket/websocket_async_echo_server.hpp +++ b/test/websocket/websocket_async_echo_server.hpp @@ -312,7 +312,7 @@ private: d.db.consume(d.db.size()); // read message d.state = 2; - d.ws.async_read(d.op, d.db, + d.ws.async_read(d.db, d.strand.wrap(std::move(*this))); return; @@ -357,7 +357,7 @@ private: } // write message d.state = 1; - d.ws.binary(d.op == beast::websocket::opcode::binary); + d.ws.binary(d.ws.got_binary()); d.ws.async_write(d.db.data(), d.strand.wrap(std::move(*this))); return; diff --git a/test/websocket/websocket_sync_echo_server.hpp b/test/websocket/websocket_sync_echo_server.hpp index 38a6e474..e20dd41c 100644 --- a/test/websocket/websocket_sync_echo_server.hpp +++ b/test/websocket/websocket_sync_echo_server.hpp @@ -304,15 +304,14 @@ private: } for(;;) { - beast::websocket::opcode op; beast::multi_buffer b; - ws.read(op, b, ec); + ws.read(b, ec); if(ec) { auto const s = ec.message(); break; } - ws.binary(op == beast::websocket::opcode::binary); + ws.binary(ws.got_binary()); if(match(b, "RAW")) { boost::asio::write(