From 9774ed0e19735456cd276792b6e4762447b0fa32 Mon Sep 17 00:00:00 2001 From: Vinnie Falco Date: Fri, 21 Apr 2017 11:46:51 -0700 Subject: [PATCH] Make websocket::close_code a proper enum: fix #311 This changes close_code to be a proper enumeration. --- CHANGELOG.md | 1 + include/beast/websocket/detail/frame.hpp | 40 ++++---- .../beast/websocket/detail/stream_base.hpp | 10 +- include/beast/websocket/impl/read.ipp | 4 +- include/beast/websocket/rfc6455.hpp | 91 +++++++++++++------ test/websocket/frame.cpp | 34 +++---- 6 files changed, 109 insertions(+), 71 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0aea4921..4e88f105 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ * Add Appveyor build scripts and badge * Tidy up MSVC CMake configuration +* Make close_code a proper enum -------------------------------------------------------------------------------- diff --git a/include/beast/websocket/detail/frame.hpp b/include/beast/websocket/detail/frame.hpp index c3def4f3..2a0cb628 100644 --- a/include/beast/websocket/detail/frame.hpp +++ b/include/beast/websocket/detail/frame.hpp @@ -67,33 +67,31 @@ is_control(opcode op) return op >= opcode::close; } -// Returns `true` if a close code is valid inline bool -is_valid(close_code::value code) +is_valid_close_code(std::uint16_t v) { - auto const v = code; switch(v) { - case 1000: - case 1001: - case 1002: - case 1003: - case 1007: - case 1008: - case 1009: - case 1010: - case 1011: - case 1012: - case 1013: + case close_code::normal: // 1000 + case close_code::going_away: // 1001 + case close_code::protocol_error: // 1002 + case close_code::unknown_data: // 1003 + case close_code::bad_payload: // 1007 + case close_code::policy_error: // 1008 + case close_code::too_big: // 1009 + case close_code::needs_extension: // 1010 + case close_code::internal_error: // 1011 + case close_code::service_restart: // 1012 + case close_code::try_again_later: // 1013 return true; // explicitly reserved - case 1004: - case 1005: - case 1006: - case 1014: - case 1015: + case close_code::reserved1: // 1004 + case close_code::no_status: // 1005 + case close_code::abnormal: // 1006 + case close_code::reserved2: // 1014 + case close_code::reserved3: // 1015 return false; } // reserved @@ -175,7 +173,7 @@ read(ping_data& data, Buffers const& bs) template void read(close_reason& cr, - Buffers const& bs, close_code::value& code) + Buffers const& bs, close_code& code) { using boost::asio::buffer; using boost::asio::buffer_copy; @@ -201,7 +199,7 @@ read(close_reason& cr, cr.code = big_uint16_to_native(&b[0]); cb.consume(2); n -= 2; - if(! is_valid(cr.code)) + if(! is_valid_close_code(cr.code)) { code = close_code::protocol_error; return; diff --git a/include/beast/websocket/detail/stream_base.hpp b/include/beast/websocket/detail/stream_base.hpp index 6cd6731f..7ba05260 100644 --- a/include/beast/websocket/detail/stream_base.hpp +++ b/include/beast/websocket/detail/stream_base.hpp @@ -175,12 +175,12 @@ protected: template std::size_t read_fh1(detail::frame_header& fh, - DynamicBuffer& db, close_code::value& code); + DynamicBuffer& db, close_code& code); template void read_fh2(detail::frame_header& fh, - DynamicBuffer& db, close_code::value& code); + DynamicBuffer& db, close_code& code); // Called before receiving the first frame of each message template @@ -264,13 +264,13 @@ template std::size_t stream_base:: read_fh1(detail::frame_header& fh, - DynamicBuffer& db, close_code::value& code) + DynamicBuffer& db, close_code& code) { using boost::asio::buffer; using boost::asio::buffer_copy; using boost::asio::buffer_size; auto const err = - [&](close_code::value cv) + [&](close_code cv) { code = cv; return 0; @@ -372,7 +372,7 @@ template void stream_base:: read_fh2(detail::frame_header& fh, - DynamicBuffer& db, close_code::value& code) + DynamicBuffer& db, close_code& code) { using boost::asio::buffer; using boost::asio::buffer_copy; diff --git a/include/beast/websocket/impl/read.ipp b/include/beast/websocket/impl/read.ipp index 4defa674..acb940c9 100644 --- a/include/beast/websocket/impl/read.ipp +++ b/include/beast/websocket/impl/read.ipp @@ -173,7 +173,7 @@ operator()(error_code ec, if(! ec) { d.cont = d.cont || again; - close_code::value code = close_code::none; + close_code code = close_code::none; do { switch(d.state) @@ -727,7 +727,7 @@ read_frame(frame_info& fi, DynamicBuffer& dynabuf, error_code& ec) using boost::asio::buffer; using boost::asio::buffer_cast; using boost::asio::buffer_size; - close_code::value code{}; + close_code code{}; for(;;) { // Read frame header diff --git a/include/beast/websocket/rfc6455.hpp b/include/beast/websocket/rfc6455.hpp index 3acb11e5..6051ebff 100644 --- a/include/beast/websocket/rfc6455.hpp +++ b/include/beast/websocket/rfc6455.hpp @@ -45,48 +45,87 @@ enum class opcode : std::uint8_t @see RFC 6455 7.4.1 Defined Status Codes */ -#if GENERATING_DOCS enum close_code -#else -namespace close_code { -using value = std::uint16_t; -enum -#endif { - /// used internally to mean "no error" - none = 0, - + /// Normal closure; the connection successfully completed whatever purpose for which it was created. normal = 1000, + + /// The endpoint is going away, either because of a server failure or because the browser is navigating away from the page that opened the connection. going_away = 1001, + + /// The endpoint is terminating the connection due to a protocol error. protocol_error = 1002, + /// The connection is being terminated because the endpoint received data of a type it cannot accept (for example, a text-only endpoint received binary data). unknown_data = 1003, - /// Indicates a received close frame has no close code - //no_code = 1005, // TODO - - /// Indicates the connection was closed without receiving a close frame - no_close = 1006, - + /// The endpoint is terminating the connection because a message was received that contained inconsistent data (e.g., non-UTF-8 data within a text message). bad_payload = 1007, + + /// The endpoint is terminating the connection because it received a message that violates its policy. This is a generic status code, used when codes 1003 and 1009 are not suitable. policy_error = 1008, + + /// The endpoint is terminating the connection because a data frame was received that is too large. too_big = 1009, + + /// The client is terminating the connection because it expected the server to negotiate one or more extension, but the server didn't. needs_extension = 1010, + + /// The server is terminating the connection because it encountered an unexpected condition that prevented it from fulfilling the request. internal_error = 1011, + /// The server is terminating the connection because it is restarting. service_restart = 1012, + + /// The server is terminating the connection due to a temporary condition, e.g. it is overloaded and is casting off some of its clients. try_again_later = 1013, - reserved1 = 1004, - no_status = 1005, // illegal on wire - abnormal = 1006, // illegal on wire - reserved2 = 1015, + //---- + // + // The following are illegal on the wire + // - last = 5000 // satisfy warnings + /** Used internally to mean "no error" + + This code is reserved and may not be sent. + */ + none = 0, + + /** Reserved for future use by the WebSocket standard. + + This code is reserved and may not be sent. + */ + reserved1 = 1004, + + /** No status code was provided even though one was expected. + + This code is reserved and may not be sent. + */ + no_status = 1005, + + /** Connection was closed without receiving a close frame + + This code is reserved and may not be sent. + */ + abnormal = 1006, + + /** Reserved for future use by the WebSocket standard. + + This code is reserved and may not be sent. + */ + reserved2 = 1014, + + /** Reserved for future use by the WebSocket standard. + + This code is reserved and may not be sent. + */ + reserved3 = 1015 + + // + //---- + + //last = 5000 // satisfy warnings }; -#if ! GENERATING_DOCS -} // close_code -#endif /// The type representing the reason string in a close frame. using reason_string = static_string<123, char>; @@ -102,7 +141,7 @@ using ping_data = static_string<125, char>; struct close_reason { /// The close code. - close_code::value code = close_code::none; + std::uint16_t code = close_code::none; /// The optional utf8-encoded reason string. reason_string reason; @@ -115,7 +154,7 @@ struct close_reason close_reason() = default; /// Construct from a code. - close_reason(close_code::value code_) + close_reason(std::uint16_t code_) : code(code_) { } @@ -130,7 +169,7 @@ struct close_reason /// Construct from a code and reason. template - close_reason(close_code::value code_, + close_reason(close_code code_, char const (&reason_)[N]) : code(code_) , reason(reason_) diff --git a/test/websocket/frame.cpp b/test/websocket/frame.cpp index 13d2c510..550a49a5 100644 --- a/test/websocket/frame.cpp +++ b/test/websocket/frame.cpp @@ -35,20 +35,20 @@ class frame_test : public beast::unit_test::suite public: void testCloseCodes() { - BEAST_EXPECT(! is_valid(0)); - BEAST_EXPECT(! is_valid(1)); - BEAST_EXPECT(! is_valid(999)); - BEAST_EXPECT(! is_valid(1004)); - BEAST_EXPECT(! is_valid(1005)); - BEAST_EXPECT(! is_valid(1006)); - BEAST_EXPECT(! is_valid(1016)); - BEAST_EXPECT(! is_valid(2000)); - BEAST_EXPECT(! is_valid(2999)); - BEAST_EXPECT(is_valid(1000)); - BEAST_EXPECT(is_valid(1002)); - BEAST_EXPECT(is_valid(3000)); - BEAST_EXPECT(is_valid(4000)); - BEAST_EXPECT(is_valid(5000)); + BEAST_EXPECT(! is_valid_close_code(0)); + BEAST_EXPECT(! is_valid_close_code(1)); + BEAST_EXPECT(! is_valid_close_code(999)); + BEAST_EXPECT(! is_valid_close_code(1004)); + BEAST_EXPECT(! is_valid_close_code(1005)); + BEAST_EXPECT(! is_valid_close_code(1006)); + BEAST_EXPECT(! is_valid_close_code(1016)); + BEAST_EXPECT(! is_valid_close_code(2000)); + BEAST_EXPECT(! is_valid_close_code(2999)); + BEAST_EXPECT(is_valid_close_code(1000)); + BEAST_EXPECT(is_valid_close_code(1002)); + BEAST_EXPECT(is_valid_close_code(3000)); + BEAST_EXPECT(is_valid_close_code(4000)); + BEAST_EXPECT(is_valid_close_code(5000)); } struct test_fh : frame_header @@ -77,7 +77,7 @@ public: { fh_streambuf sb; write(sb, fh); - close_code::value code; + close_code code; stream_base stream; stream.open(role); detail::frame_header fh1; @@ -129,7 +129,7 @@ public: { fh_streambuf sb; write(sb, fh); - close_code::value code; + close_code code; stream_base stream; stream.open(role); detail::frame_header fh1; @@ -197,7 +197,7 @@ public: sb.commit(buffer_copy(sb.prepare(v.size()), buffer(v))); stream_base stream; stream.open(role); - close_code::value code; + close_code code; detail::frame_header fh; auto const n = stream.read_fh1(fh, sb, code);