Add WebSocket error conditions:

This introduces the condition enumeration type for grouping
websocket error codes together as a convenience to callers.
This commit is contained in:
Vinnie Falco
2018-01-01 13:13:43 -08:00
parent b86169019e
commit 08a9ed4c25
5 changed files with 116 additions and 9 deletions

View File

@@ -6,6 +6,7 @@ WebSocket:
* Redistribute the read tests in the translation units
* Refactor error headers
* Add WebSocket error conditions
--------------------------------------------------------------------------------

View File

@@ -18,6 +18,7 @@ namespace boost {
namespace beast {
namespace websocket {
enum class error;
enum class condition;
} // websocket
} // beast
@@ -27,6 +28,11 @@ struct is_error_code_enum<beast::websocket::error>
{
static bool const value = true;
};
template<>
struct is_error_condition_enum<beast::websocket::condition>
{
static bool const value = true;
};
} // system
namespace beast {
@@ -37,7 +43,7 @@ class error_codes : public error_category
{
template<class = void>
string_view
get_message(error ev) const;
message(error e) const;
public:
const char*
@@ -49,7 +55,43 @@ public:
std::string
message(int ev) const override
{
return get_message(static_cast<error>(ev)).to_string();
return message(
static_cast<error>(ev)).to_string();
}
};
class error_conditions : public error_category
{
template<class = void>
string_view
message(condition c) const;
template<class = void>
bool
equivalent(error_code const& ec,
condition c) const noexcept;
public:
const char*
name() const noexcept override
{
return "boost.beast.websocket";
}
std::string
message(int cv) const override
{
return message(
static_cast<condition>(cv)).to_string();
}
bool
equivalent(
error_code const& ec,
int cv) const noexcept
{
return equivalent(ec,
static_cast<condition>(cv));
}
};
@@ -64,6 +106,15 @@ make_error_code(error e)
std::underlying_type<error>::type>(e), cat};
}
inline
error_condition
make_error_condition(condition c)
{
static detail::error_conditions const cat{};
return error_condition{static_cast<
std::underlying_type<condition>::type>(c), cat};
}
} // websocket
} // beast

View File

@@ -37,6 +37,18 @@ enum class error
partial_deflate_block
};
/// Error conditions corresponding to sets of error codes.
enum class condition
{
/** Handshake failed
This condition indicates that the WebSocket handshake failed. If
the corresponding HTTP response indicates the keep-alive behavior,
then the handshake may be reattempted.
*/
handshake_failed = 1,
};
} // websocket
} // beast
} // boost

View File

@@ -18,9 +18,9 @@ namespace detail {
template<class>
string_view
error_codes::
get_message(error ev) const
message(error e) const
{
switch(ev)
switch(e)
{
default:
case error::failed: return "WebSocket connection failed due to a protocol violation";
@@ -31,6 +31,42 @@ get_message(error ev) const
}
}
template<class>
string_view
error_conditions::
message(condition c) const
{
switch(c)
{
default:
case condition::handshake_failed: return "WebSocket upgrade handshake failed";
}
}
template<class>
bool
error_conditions::
equivalent(
error_code const& ec,
condition c) const noexcept
{
if(ec.category() == error_code{error{}}.category())
{
switch(c)
{
case condition::handshake_failed:
switch(static_cast<error>(ec.value()))
{
case error::handshake_failed:
return true;
}
return false;
}
}
return false;
}
} // detail
} // websocket
} // beast

View File

@@ -20,23 +20,28 @@ namespace websocket {
class error_test : public unit_test::suite
{
public:
void check(error ev)
void check(error e)
{
auto const ec = make_error_code(ev);
auto const ec = make_error_code(e);
ec.category().name();
BEAST_EXPECT(! ec.message().empty());
#if 0
BEAST_EXPECT(std::addressof(ec.category()) ==
std::addressof(detail::get_error_category()));
BEAST_EXPECT(detail::get_error_category().equivalent(
static_cast<std::underlying_type<error>::type>(ev),
static_cast<std::underlying_type<error>::type>(e),
ec.category().default_error_condition(
static_cast<std::underlying_type<error>::type>(ev))));
static_cast<std::underlying_type<error>::type>(e))));
BEAST_EXPECT(detail::get_error_category().equivalent(
ec, static_cast<std::underlying_type<error>::type>(ev)));
ec, static_cast<std::underlying_type<error>::type>(e)));
#endif
}
void check(error e, condition c)
{
BEAST_EXPECT(error_code{e} == c);
}
void run() override
{
check(error::closed);
@@ -44,6 +49,8 @@ public:
check(error::handshake_failed);
check(error::buffer_overflow);
check(error::partial_deflate_block);
check(error::handshake_failed, condition::handshake_failed);
}
};