WebSocket++  0.8.3-dev
C++ websocket client/server library
base.hpp
1 /*
2  * Copyright (c) 2014, Peter Thorson. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  * * Redistributions of source code must retain the above copyright
7  * notice, this list of conditions and the following disclaimer.
8  * * Redistributions in binary form must reproduce the above copyright
9  * notice, this list of conditions and the following disclaimer in the
10  * documentation and/or other materials provided with the distribution.
11  * * Neither the name of the WebSocket++ Project nor the
12  * names of its contributors may be used to endorse or promote products
13  * derived from this software without specific prior written permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY
19  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *
26  */
27 
28 #ifndef WEBSOCKETPP_PROCESSOR_BASE_HPP
29 #define WEBSOCKETPP_PROCESSOR_BASE_HPP
30 
31 #include <websocketpp/close.hpp>
32 #include <websocketpp/utilities.hpp>
33 #include <websocketpp/uri.hpp>
34 
35 #include <websocketpp/common/cpp11.hpp>
36 #include <websocketpp/common/system_error.hpp>
37 
38 #include <string>
39 
40 namespace websocketpp {
41 namespace processor {
42 
43 /// Constants related to processing WebSocket connections
44 namespace constants {
45 
46 static char const upgrade_token[] = "websocket";
47 static char const connection_token[] = "Upgrade";
48 static char const handshake_guid[] = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
49 
50 } // namespace constants
51 
52 
53 /// Processor class related error codes
54 namespace error_cat {
55 enum value {
56  BAD_REQUEST = 0, // Error was the result of improperly formatted user input
57  INTERNAL_ERROR = 1, // Error was a logic error internal to WebSocket++
58  PROTOCOL_VIOLATION = 2,
59  MESSAGE_TOO_BIG = 3,
60  PAYLOAD_VIOLATION = 4 // Error was due to receiving invalid payload data
61 };
62 } // namespace error_cat
63 
64 /// Error code category and codes used by all processor types
65 namespace error {
67  /// Catch-all error for processor policy errors that don't fit in other
68  /// categories
69  general = 1,
70 
71  /// Error was the result of improperly formatted user input
73 
74  /// Processor encountered a protocol violation in an incoming message
76 
77  /// Processor encountered a message that was too large
79 
80  /// Processor encountered invalid payload data.
82 
83  /// The processor method was called with invalid arguments
85 
86  /// Opcode was invalid for requested operation
88 
89  /// Control frame too large
91 
92  /// Illegal use of reserved bit
94 
95  /// Fragmented control message
97 
98  /// Continuation without message
100 
101  /// Clients may not send unmasked frames
103 
104  /// Servers may not send masked frames
106 
107  /// Payload length not minimally encoded
109 
110  /// Not supported on 32 bit systems
112 
113  /// Invalid UTF-8 encoding
115 
116  /// Operation required not implemented functionality
118 
119  /// Invalid HTTP method
121 
122  /// Invalid HTTP version
124 
125  /// Invalid HTTP status
127 
128  /// Missing Required Header
130 
131  /// Embedded SHA-1 library error
133 
134  /// No support for this feature in this protocol version.
136 
137  /// Reserved close code used
139 
140  /// Invalid close code used
142 
143  /// Using a reason requires a close code
145 
146  /// Error parsing subprotocols
148 
149  /// Error parsing extensions
151 
152  /// Extension related operation was ignored because extensions are disabled
154 
155  /// Short Ke3 read. Hybi00 requires a third key to be read from the 8 bytes
156  /// after the handshake. Less than 8 bytes were read.
157  short_key3
158 };
159 
160 /// Category for processor errors
161 class processor_category : public lib::error_category {
162 public:
163  processor_category() {}
164 
165  char const * name() const _WEBSOCKETPP_NOEXCEPT_TOKEN_ {
166  return "websocketpp.processor";
167  }
168 
169  std::string message(int value) const {
170  switch(value) {
171  case error::general:
172  return "Generic processor error";
173  case error::bad_request:
174  return "invalid user input";
175  case error::protocol_violation:
176  return "Generic protocol violation";
177  case error::message_too_big:
178  return "A message was too large";
179  case error::invalid_payload:
180  return "A payload contained invalid data";
181  case error::invalid_arguments:
182  return "invalid function arguments";
183  case error::invalid_opcode:
184  return "invalid opcode";
185  case error::control_too_big:
186  return "Control messages are limited to fewer than 125 characters";
187  case error::invalid_rsv_bit:
188  return "Invalid use of reserved bits";
189  case error::fragmented_control:
190  return "Control messages cannot be fragmented";
191  case error::invalid_continuation:
192  return "Invalid message continuation";
193  case error::masking_required:
194  return "Clients may not send unmasked frames";
195  case error::masking_forbidden:
196  return "Servers may not send masked frames";
197  case error::non_minimal_encoding:
198  return "Payload length was not minimally encoded";
199  case error::requires_64bit:
200  return "64 bit frames are not supported on 32 bit systems";
201  case error::invalid_utf8:
202  return "Invalid UTF8 encoding";
203  case error::not_implemented:
204  return "Operation required not implemented functionality";
205  case error::invalid_http_method:
206  return "Invalid HTTP method.";
207  case error::invalid_http_version:
208  return "Invalid HTTP version.";
209  case error::invalid_http_status:
210  return "Invalid HTTP status.";
211  case error::missing_required_header:
212  return "A required HTTP header is missing";
213  case error::sha1_library:
214  return "SHA-1 library error";
215  case error::no_protocol_support:
216  return "The WebSocket protocol version in use does not support this feature";
217  case error::reserved_close_code:
218  return "Reserved close code used";
219  case error::invalid_close_code:
220  return "Invalid close code used";
221  case error::reason_requires_code:
222  return "Using a close reason requires a valid close code";
223  case error::subprotocol_parse_error:
224  return "Error parsing subprotocol header";
225  case error::extension_parse_error:
226  return "Error parsing extension header";
227  case error::extensions_disabled:
228  return "Extensions are disabled";
229  case error::short_key3:
230  return "Short Hybi00 Key 3 read";
231  default:
232  return "Unknown";
233  }
234  }
235 };
236 
237 /// Get a reference to a static copy of the processor error category
239  static processor_category instance;
240  return instance;
241 }
242 
243 /// Create an error code with the given value and the processor category
245  return lib::error_code(static_cast<int>(e), get_processor_category());
246 }
247 
248 /// Converts a processor error_code into a websocket close code
249 /**
250  * Looks up the appropriate WebSocket close code that should be sent after an
251  * error of this sort occurred.
252  *
253  * If the error is not in the processor category close::status::blank is
254  * returned.
255  *
256  * If the error isn't normally associated with reasons to close a connection
257  * (such as errors intended to be used internally or delivered to client
258  * applications, ex: invalid arguments) then
259  * close::status::internal_endpoint_error is returned.
260  */
262  if (ec.category() != get_processor_category()) {
263  return close::status::blank;
264  }
265 
266  switch (ec.value()) {
267  case error::protocol_violation:
268  case error::control_too_big:
269  case error::invalid_opcode:
270  case error::invalid_rsv_bit:
271  case error::fragmented_control:
272  case error::invalid_continuation:
273  case error::masking_required:
274  case error::masking_forbidden:
275  case error::reserved_close_code:
276  case error::invalid_close_code:
277  return close::status::protocol_error;
278  case error::invalid_payload:
279  case error::invalid_utf8:
280  return close::status::invalid_payload;
281  case error::message_too_big:
282  return close::status::message_too_big;
283  default:
284  return close::status::internal_endpoint_error;
285  }
286 }
287 
288 } // namespace error
289 } // namespace processor
290 } // namespace websocketpp
291 
292 _WEBSOCKETPP_ERROR_CODE_ENUM_NS_START_
293 template<> struct is_error_code_enum<websocketpp::processor::error::processor_errors>
294 {
295  static bool const value = true;
296 };
297 _WEBSOCKETPP_ERROR_CODE_ENUM_NS_END_
298 
299 #endif //WEBSOCKETPP_PROCESSOR_BASE_HPP
websocketpp::processor::error::processor_errors
processor_errors
Definition: base.hpp:66
websocketpp::processor::error::non_minimal_encoding
@ non_minimal_encoding
Payload length not minimally encoded.
Definition: base.hpp:108
websocketpp::processor::error
Error code category and codes used by all processor types.
Definition: base.hpp:65
websocketpp::processor::error::reason_requires_code
@ reason_requires_code
Using a reason requires a close code.
Definition: base.hpp:144
websocketpp::processor::error::invalid_rsv_bit
@ invalid_rsv_bit
Illegal use of reserved bit.
Definition: base.hpp:93
websocketpp::processor::error::no_protocol_support
@ no_protocol_support
No support for this feature in this protocol version.
Definition: base.hpp:135
websocketpp::processor::error::extensions_disabled
@ extensions_disabled
Extension related operation was ignored because extensions are disabled.
Definition: base.hpp:153
websocketpp::processor::error::not_implemented
@ not_implemented
Operation required not implemented functionality.
Definition: base.hpp:117
websocketpp::processor::error::invalid_payload
@ invalid_payload
Processor encountered invalid payload data.
Definition: base.hpp:81
websocketpp::processor::error::general
@ general
Definition: base.hpp:69
websocketpp::processor::error::get_processor_category
lib::error_category const & get_processor_category()
Get a reference to a static copy of the processor error category.
Definition: base.hpp:238
websocketpp::processor::constants
Constants related to processing WebSocket connections.
Definition: base.hpp:44
websocketpp::versions_supported
static std::vector< int > const versions_supported(helper, helper+4)
Container that stores the list of protocol versions supported.
websocketpp::processor::error::bad_request
@ bad_request
Error was the result of improperly formatted user input.
Definition: base.hpp:72
websocketpp::processor::error::invalid_http_version
@ invalid_http_version
Invalid HTTP version.
Definition: base.hpp:123
websocketpp::processor::error::protocol_violation
@ protocol_violation
Processor encountered a protocol violation in an incoming message.
Definition: base.hpp:75
websocketpp::processor::error::invalid_http_status
@ invalid_http_status
Invalid HTTP status.
Definition: base.hpp:126
websocketpp::processor::error::make_error_code
lib::error_code make_error_code(error::processor_errors e)
Create an error code with the given value and the processor category.
Definition: base.hpp:244
websocketpp::processor::error::missing_required_header
@ missing_required_header
Missing Required Header.
Definition: base.hpp:129
websocketpp::processor::error::to_ws
close::status::value to_ws(lib::error_code ec)
Converts a processor error_code into a websocket close code.
Definition: base.hpp:261
websocketpp::processor::error::invalid_http_method
@ invalid_http_method
Invalid HTTP method.
Definition: base.hpp:120
websocketpp::processor::error::invalid_continuation
@ invalid_continuation
Continuation without message.
Definition: base.hpp:99
websocketpp::processor::error::requires_64bit
@ requires_64bit
Not supported on 32 bit systems.
Definition: base.hpp:111
websocketpp::processor::error::fragmented_control
@ fragmented_control
Fragmented control message.
Definition: base.hpp:96
websocketpp::processor::error_cat
Processor class related error codes.
Definition: base.hpp:54
websocketpp::processor::error::masking_forbidden
@ masking_forbidden
Servers may not send masked frames.
Definition: base.hpp:105
websocketpp::processor
Processors encapsulate the protocol rules specific to each WebSocket version.
Definition: base.hpp:41
websocketpp::processor::error::subprotocol_parse_error
@ subprotocol_parse_error
Error parsing subprotocols.
Definition: base.hpp:147
websocketpp::processor::error::reserved_close_code
@ reserved_close_code
Reserved close code used.
Definition: base.hpp:138
websocketpp::processor::error::message_too_big
@ message_too_big
Processor encountered a message that was too large.
Definition: base.hpp:78
websocketpp::processor::error::invalid_close_code
@ invalid_close_code
Invalid close code used.
Definition: base.hpp:141
websocketpp::processor::error::control_too_big
@ control_too_big
Control frame too large.
Definition: base.hpp:90
websocketpp::processor::error::short_key3
@ short_key3
Definition: base.hpp:157
websocketpp::processor::error::extension_parse_error
@ extension_parse_error
Error parsing extensions.
Definition: base.hpp:150
websocketpp::processor::error::invalid_arguments
@ invalid_arguments
The processor method was called with invalid arguments.
Definition: base.hpp:84
websocketpp::processor::error::invalid_utf8
@ invalid_utf8
Invalid UTF-8 encoding.
Definition: base.hpp:114
websocketpp::processor::error::sha1_library
@ sha1_library
Embedded SHA-1 library error.
Definition: base.hpp:132
websocketpp::processor::error::masking_required
@ masking_required
Clients may not send unmasked frames.
Definition: base.hpp:102
websocketpp::processor::error::invalid_opcode
@ invalid_opcode
Opcode was invalid for requested operation.
Definition: base.hpp:87