base.hpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  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. #ifndef WEBSOCKETPP_PROCESSOR_BASE_HPP
  28. #define WEBSOCKETPP_PROCESSOR_BASE_HPP
  29. #include <websocketpp/close.hpp>
  30. #include <websocketpp/utilities.hpp>
  31. #include <websocketpp/uri.hpp>
  32. #include <websocketpp/common/cpp11.hpp>
  33. #include <websocketpp/common/system_error.hpp>
  34. #include <string>
  35. namespace websocketpp {
  36. namespace processor {
  37. /// Constants related to processing WebSocket connections
  38. namespace constants {
  39. static char const upgrade_token[] = "websocket";
  40. static char const connection_token[] = "Upgrade";
  41. static char const handshake_guid[] = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
  42. } // namespace constants
  43. /// Processor class related error codes
  44. namespace error_cat {
  45. enum value {
  46. BAD_REQUEST = 0, // Error was the result of improperly formatted user input
  47. INTERNAL_ERROR = 1, // Error was a logic error internal to WebSocket++
  48. PROTOCOL_VIOLATION = 2,
  49. MESSAGE_TOO_BIG = 3,
  50. PAYLOAD_VIOLATION = 4 // Error was due to receiving invalid payload data
  51. };
  52. } // namespace error_cat
  53. /// Error code category and codes used by all processor types
  54. namespace error {
  55. enum processor_errors {
  56. /// Catch-all error for processor policy errors that don't fit in other
  57. /// categories
  58. general = 1,
  59. /// Error was the result of improperly formatted user input
  60. bad_request,
  61. /// Processor encountered a protocol violation in an incoming message
  62. protocol_violation,
  63. /// Processor encountered a message that was too large
  64. message_too_big,
  65. /// Processor encountered invalid payload data.
  66. invalid_payload,
  67. /// The processor method was called with invalid arguments
  68. invalid_arguments,
  69. /// Opcode was invalid for requested operation
  70. invalid_opcode,
  71. /// Control frame too large
  72. control_too_big,
  73. /// Illegal use of reserved bit
  74. invalid_rsv_bit,
  75. /// Fragmented control message
  76. fragmented_control,
  77. /// Continuation without message
  78. invalid_continuation,
  79. /// Clients may not send unmasked frames
  80. masking_required,
  81. /// Servers may not send masked frames
  82. masking_forbidden,
  83. /// Payload length not minimally encoded
  84. non_minimal_encoding,
  85. /// Not supported on 32 bit systems
  86. requires_64bit,
  87. /// Invalid UTF-8 encoding
  88. invalid_utf8,
  89. /// Operation required not implemented functionality
  90. not_implemented,
  91. /// Invalid HTTP method
  92. invalid_http_method,
  93. /// Invalid HTTP version
  94. invalid_http_version,
  95. /// Invalid HTTP status
  96. invalid_http_status,
  97. /// Missing Required Header
  98. missing_required_header,
  99. /// Embedded SHA-1 library error
  100. sha1_library,
  101. /// No support for this feature in this protocol version.
  102. no_protocol_support,
  103. /// Reserved close code used
  104. reserved_close_code,
  105. /// Invalid close code used
  106. invalid_close_code,
  107. /// Using a reason requires a close code
  108. reason_requires_code,
  109. /// Error parsing subprotocols
  110. subprotocol_parse_error,
  111. /// Error parsing extensions
  112. extension_parse_error,
  113. /// Extension related operation was ignored because extensions are disabled
  114. extensions_disabled,
  115. /// Short Ke3 read. Hybi00 requires a third key to be read from the 8 bytes
  116. /// after the handshake. Less than 8 bytes were read.
  117. short_key3
  118. };
  119. /// Category for processor errors
  120. class processor_category : public lib::error_category {
  121. public:
  122. processor_category() {}
  123. char const * name() const _WEBSOCKETPP_NOEXCEPT_TOKEN_ {
  124. return "websocketpp.processor";
  125. }
  126. std::string message(int value) const {
  127. switch(value) {
  128. case error::general:
  129. return "Generic processor error";
  130. case error::bad_request:
  131. return "invalid user input";
  132. case error::protocol_violation:
  133. return "Generic protocol violation";
  134. case error::message_too_big:
  135. return "A message was too large";
  136. case error::invalid_payload:
  137. return "A payload contained invalid data";
  138. case error::invalid_arguments:
  139. return "invalid function arguments";
  140. case error::invalid_opcode:
  141. return "invalid opcode";
  142. case error::control_too_big:
  143. return "Control messages are limited to fewer than 125 characters";
  144. case error::invalid_rsv_bit:
  145. return "Invalid use of reserved bits";
  146. case error::fragmented_control:
  147. return "Control messages cannot be fragmented";
  148. case error::invalid_continuation:
  149. return "Invalid message continuation";
  150. case error::masking_required:
  151. return "Clients may not send unmasked frames";
  152. case error::masking_forbidden:
  153. return "Servers may not send masked frames";
  154. case error::non_minimal_encoding:
  155. return "Payload length was not minimally encoded";
  156. case error::requires_64bit:
  157. return "64 bit frames are not supported on 32 bit systems";
  158. case error::invalid_utf8:
  159. return "Invalid UTF8 encoding";
  160. case error::not_implemented:
  161. return "Operation required not implemented functionality";
  162. case error::invalid_http_method:
  163. return "Invalid HTTP method.";
  164. case error::invalid_http_version:
  165. return "Invalid HTTP version.";
  166. case error::invalid_http_status:
  167. return "Invalid HTTP status.";
  168. case error::missing_required_header:
  169. return "A required HTTP header is missing";
  170. case error::sha1_library:
  171. return "SHA-1 library error";
  172. case error::no_protocol_support:
  173. return "The WebSocket protocol version in use does not support this feature";
  174. case error::reserved_close_code:
  175. return "Reserved close code used";
  176. case error::invalid_close_code:
  177. return "Invalid close code used";
  178. case error::reason_requires_code:
  179. return "Using a close reason requires a valid close code";
  180. case error::subprotocol_parse_error:
  181. return "Error parsing subprotocol header";
  182. case error::extension_parse_error:
  183. return "Error parsing extension header";
  184. case error::extensions_disabled:
  185. return "Extensions are disabled";
  186. case error::short_key3:
  187. return "Short Hybi00 Key 3 read";
  188. default:
  189. return "Unknown";
  190. }
  191. }
  192. };
  193. /// Get a reference to a static copy of the processor error category
  194. inline lib::error_category const & get_processor_category() {
  195. static processor_category instance;
  196. return instance;
  197. }
  198. /// Create an error code with the given value and the processor category
  199. inline lib::error_code make_error_code(error::processor_errors e) {
  200. return lib::error_code(static_cast<int>(e), get_processor_category());
  201. }
  202. /// Converts a processor error_code into a websocket close code
  203. /**
  204. * Looks up the appropriate WebSocket close code that should be sent after an
  205. * error of this sort occurred.
  206. *
  207. * If the error is not in the processor category close::status::blank is
  208. * returned.
  209. *
  210. * If the error isn't normally associated with reasons to close a connection
  211. * (such as errors intended to be used internally or delivered to client
  212. * applications, ex: invalid arguments) then
  213. * close::status::internal_endpoint_error is returned.
  214. */
  215. inline close::status::value to_ws(lib::error_code ec) {
  216. if (ec.category() != get_processor_category()) {
  217. return close::status::blank;
  218. }
  219. switch (ec.value()) {
  220. case error::protocol_violation:
  221. case error::control_too_big:
  222. case error::invalid_opcode:
  223. case error::invalid_rsv_bit:
  224. case error::fragmented_control:
  225. case error::invalid_continuation:
  226. case error::masking_required:
  227. case error::masking_forbidden:
  228. case error::reserved_close_code:
  229. case error::invalid_close_code:
  230. return close::status::protocol_error;
  231. case error::invalid_payload:
  232. case error::invalid_utf8:
  233. return close::status::invalid_payload;
  234. case error::message_too_big:
  235. return close::status::message_too_big;
  236. default:
  237. return close::status::internal_endpoint_error;
  238. }
  239. }
  240. } // namespace error
  241. } // namespace processor
  242. } // namespace websocketpp
  243. _WEBSOCKETPP_ERROR_CODE_ENUM_NS_START_
  244. template<> struct is_error_code_enum<websocketpp::processor::error::processor_errors>
  245. {
  246. static bool const value = true;
  247. };
  248. _WEBSOCKETPP_ERROR_CODE_ENUM_NS_END_
  249. #endif //WEBSOCKETPP_PROCESSOR_BASE_HPP