Make websocket::close_code a proper enum:

fix #311

This changes close_code to be a proper enumeration.
This commit is contained in:
Vinnie Falco
2017-04-21 11:46:51 -07:00
parent bd4ad15856
commit 9774ed0e19
6 changed files with 109 additions and 71 deletions

View File

@@ -2,6 +2,7 @@
* Add Appveyor build scripts and badge
* Tidy up MSVC CMake configuration
* Make close_code a proper enum
--------------------------------------------------------------------------------

View File

@@ -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<class Buffers>
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;

View File

@@ -175,12 +175,12 @@ protected:
template<class DynamicBuffer>
std::size_t
read_fh1(detail::frame_header& fh,
DynamicBuffer& db, close_code::value& code);
DynamicBuffer& db, close_code& code);
template<class DynamicBuffer>
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<class = void>
@@ -264,13 +264,13 @@ template<class DynamicBuffer>
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<class DynamicBuffer>
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;

View File

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

View File

@@ -45,48 +45,87 @@ enum class opcode : std::uint8_t
@see <a href="https://tools.ietf.org/html/rfc6455#section-7.4.1">RFC 6455 7.4.1 Defined Status Codes</a>
*/
#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<std::size_t N>
close_reason(close_code::value code_,
close_reason(close_code code_,
char const (&reason_)[N])
: code(code_)
, reason(reason_)

View File

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