1//
2// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
3//
4// Distributed under the Boost Software License, Version 1.0. (See accompanying
5// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6//
7// Official repository: https://github.com/boostorg/beast
8//
9
10#ifndef BOOST_BEAST_WEBSOCKET_IMPL_ERROR_IPP
11#define BOOST_BEAST_WEBSOCKET_IMPL_ERROR_IPP
12
13#include <boost/beast/websocket/error.hpp>
14
15namespace boost {
16namespace beast {
17namespace websocket {
18namespace detail {
19
20class error_codes : public error_category
21{
22public:
23    const char*
24    name() const noexcept override
25    {
26        return "boost.beast.websocket";
27    }
28
29    std::string
30    message(int ev) const override
31    {
32        switch(static_cast<error>(ev))
33        {
34        default:
35        case error::closed:                 return "The WebSocket stream was gracefully closed at both endpoints";
36        case error::buffer_overflow:        return "The WebSocket operation caused a dynamic buffer overflow";
37        case error::partial_deflate_block:  return "The WebSocket stream produced an incomplete deflate block";
38        case error::message_too_big:        return "The WebSocket message exceeded the locally configured limit";
39
40        case error::bad_http_version:       return "The WebSocket handshake was not HTTP/1.1";
41        case error::bad_method:             return "The WebSocket handshake method was not GET";
42        case error::no_host:                return "The WebSocket handshake Host field is missing";
43        case error::no_connection:          return "The WebSocket handshake Connection field is missing";
44        case error::no_connection_upgrade:  return "The WebSocket handshake Connection field is missing the upgrade token";
45        case error::no_upgrade:             return "The WebSocket handshake Upgrade field is missing";
46        case error::no_upgrade_websocket:   return "The WebSocket handshake Upgrade field is missing the websocket token";
47        case error::no_sec_key:             return "The WebSocket handshake Sec-WebSocket-Key field is missing";
48        case error::bad_sec_key:            return "The WebSocket handshake Sec-WebSocket-Key field is invalid";
49        case error::no_sec_version:         return "The WebSocket handshake Sec-WebSocket-Version field is missing";
50        case error::bad_sec_version:        return "The WebSocket handshake Sec-WebSocket-Version field is invalid";
51        case error::no_sec_accept:          return "The WebSocket handshake Sec-WebSocket-Accept field is missing";
52        case error::bad_sec_accept:         return "The WebSocket handshake Sec-WebSocket-Accept field is invalid";
53        case error::upgrade_declined:       return "The WebSocket handshake was declined by the remote peer";
54
55        case error::bad_opcode:             return "The WebSocket frame contained an illegal opcode";
56        case error::bad_data_frame:         return "The WebSocket data frame was unexpected";
57        case error::bad_continuation:       return "The WebSocket continuation frame was unexpected";
58        case error::bad_reserved_bits:      return "The WebSocket frame contained illegal reserved bits";
59        case error::bad_control_fragment:   return "The WebSocket control frame was fragmented";
60        case error::bad_control_size:       return "The WebSocket control frame size was invalid";
61        case error::bad_unmasked_frame:     return "The WebSocket frame was unmasked";
62        case error::bad_masked_frame:       return "The WebSocket frame was masked";
63        case error::bad_size:               return "The WebSocket frame size was not canonical";
64        case error::bad_frame_payload:      return "The WebSocket frame payload was not valid utf8";
65        case error::bad_close_code:         return "The WebSocket close frame reason code was invalid";
66        case error::bad_close_size:         return "The WebSocket close frame payload size was invalid";
67        case error::bad_close_payload:      return "The WebSocket close frame payload was not valid utf8";
68        }
69    }
70
71    error_condition
72    default_error_condition(int ev) const noexcept override
73    {
74        switch(static_cast<error>(ev))
75        {
76        default:
77        case error::closed:
78        case error::buffer_overflow:
79        case error::partial_deflate_block:
80        case error::message_too_big:
81            return {ev, *this};
82
83        case error::bad_http_version:
84        case error::bad_method:
85        case error::no_host:
86        case error::no_connection:
87        case error::no_connection_upgrade:
88        case error::no_upgrade:
89        case error::no_upgrade_websocket:
90        case error::no_sec_key:
91        case error::bad_sec_key:
92        case error::no_sec_version:
93        case error::bad_sec_version:
94        case error::no_sec_accept:
95        case error::bad_sec_accept:
96        case error::upgrade_declined:
97            return condition::handshake_failed;
98
99        case error::bad_opcode:
100        case error::bad_data_frame:
101        case error::bad_continuation:
102        case error::bad_reserved_bits:
103        case error::bad_control_fragment:
104        case error::bad_control_size:
105        case error::bad_unmasked_frame:
106        case error::bad_masked_frame:
107        case error::bad_size:
108        case error::bad_frame_payload:
109        case error::bad_close_code:
110        case error::bad_close_size:
111        case error::bad_close_payload:
112            return condition::protocol_violation;
113        }
114    }
115};
116
117class error_conditions : public error_category
118{
119public:
120    const char*
121    name() const noexcept override
122    {
123        return "boost.beast.websocket";
124    }
125
126    std::string
127    message(int cv) const override
128    {
129        switch(static_cast<condition>(cv))
130        {
131        default:
132        case condition::handshake_failed: return "The WebSocket handshake failed";
133        case condition::protocol_violation: return "A WebSocket protocol violation occurred";
134        }
135    }
136};
137
138} // detail
139
140error_code
141make_error_code(error e)
142{
143    static detail::error_codes const cat{};
144    return error_code{static_cast<
145        std::underlying_type<error>::type>(e), cat};
146}
147
148error_condition
149make_error_condition(condition c)
150{
151    static detail::error_conditions const cat{};
152    return error_condition{static_cast<
153        std::underlying_type<condition>::type>(c), cat};
154}
155
156} // websocket
157} // beast
158} // boost
159
160#endif
161