forked from boostorg/beast
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:
@@ -6,6 +6,7 @@ WebSocket:
|
||||
|
||||
* Redistribute the read tests in the translation units
|
||||
* Refactor error headers
|
||||
* Add WebSocket error conditions
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user