/* * Copyright (c) 2014, Peter Thorson. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the WebSocket++ Project nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef WEBSOCKETPP_PROCESSOR_BASE_HPP #define WEBSOCKETPP_PROCESSOR_BASE_HPP #include #include #include #include #include #include namespace websocketpp { namespace processor { /// Constants related to processing WebSocket connections namespace constants { static char const upgrade_token[] = "websocket"; static char const connection_token[] = "Upgrade"; static char const handshake_guid[] = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; } // namespace constants /// Processor class related error codes namespace error_cat { enum value { BAD_REQUEST = 0, // Error was the result of improperly formatted user input INTERNAL_ERROR = 1, // Error was a logic error internal to WebSocket++ PROTOCOL_VIOLATION = 2, MESSAGE_TOO_BIG = 3, PAYLOAD_VIOLATION = 4 // Error was due to receiving invalid payload data }; } // namespace error_cat /// Error code category and codes used by all processor types namespace error { enum processor_errors { /// Catch-all error for processor policy errors that don't fit in other /// categories general = 1, /// Error was the result of improperly formatted user input bad_request, /// Processor encountered a protocol violation in an incoming message protocol_violation, /// Processor encountered a message that was too large message_too_big, /// Processor encountered invalid payload data. invalid_payload, /// The processor method was called with invalid arguments invalid_arguments, /// Opcode was invalid for requested operation invalid_opcode, /// Control frame too large control_too_big, /// Illegal use of reserved bit invalid_rsv_bit, /// Fragmented control message fragmented_control, /// Continuation without message invalid_continuation, /// Clients may not send unmasked frames masking_required, /// Servers may not send masked frames masking_forbidden, /// Payload length not minimally encoded non_minimal_encoding, /// Not supported on 32 bit systems requires_64bit, /// Invalid UTF-8 encoding invalid_utf8, /// Operation required not implemented functionality not_implemented, /// Invalid HTTP method invalid_http_method, /// Invalid HTTP version invalid_http_version, /// Invalid HTTP status invalid_http_status, /// Missing Required Header missing_required_header, /// Embedded SHA-1 library error sha1_library, /// No support for this feature in this protocol version. no_protocol_support, /// Reserved close code used reserved_close_code, /// Invalid close code used invalid_close_code, /// Using a reason requires a close code reason_requires_code, /// Error parsing subprotocols subprotocol_parse_error, /// Error parsing extensions extension_parse_error, /// Extension related operation was ignored because extensions are disabled extensions_disabled, /// Short Ke3 read. Hybi00 requires a third key to be read from the 8 bytes /// after the handshake. Less than 8 bytes were read. short_key3 }; /// Category for processor errors class processor_category : public lib::error_category { public: processor_category() {} char const * name() const _WEBSOCKETPP_NOEXCEPT_TOKEN_ { return "websocketpp.processor"; } std::string message(int value) const { switch(value) { case error::general: return "Generic processor error"; case error::bad_request: return "invalid user input"; case error::protocol_violation: return "Generic protocol violation"; case error::message_too_big: return "A message was too large"; case error::invalid_payload: return "A payload contained invalid data"; case error::invalid_arguments: return "invalid function arguments"; case error::invalid_opcode: return "invalid opcode"; case error::control_too_big: return "Control messages are limited to fewer than 125 characters"; case error::invalid_rsv_bit: return "Invalid use of reserved bits"; case error::fragmented_control: return "Control messages cannot be fragmented"; case error::invalid_continuation: return "Invalid message continuation"; case error::masking_required: return "Clients may not send unmasked frames"; case error::masking_forbidden: return "Servers may not send masked frames"; case error::non_minimal_encoding: return "Payload length was not minimally encoded"; case error::requires_64bit: return "64 bit frames are not supported on 32 bit systems"; case error::invalid_utf8: return "Invalid UTF8 encoding"; case error::not_implemented: return "Operation required not implemented functionality"; case error::invalid_http_method: return "Invalid HTTP method."; case error::invalid_http_version: return "Invalid HTTP version."; case error::invalid_http_status: return "Invalid HTTP status."; case error::missing_required_header: return "A required HTTP header is missing"; case error::sha1_library: return "SHA-1 library error"; case error::no_protocol_support: return "The WebSocket protocol version in use does not support this feature"; case error::reserved_close_code: return "Reserved close code used"; case error::invalid_close_code: return "Invalid close code used"; case error::reason_requires_code: return "Using a close reason requires a valid close code"; case error::subprotocol_parse_error: return "Error parsing subprotocol header"; case error::extension_parse_error: return "Error parsing extension header"; case error::extensions_disabled: return "Extensions are disabled"; case error::short_key3: return "Short Hybi00 Key 3 read"; default: return "Unknown"; } } }; /// Get a reference to a static copy of the processor error category inline lib::error_category const & get_processor_category() { static processor_category instance; return instance; } /// Create an error code with the given value and the processor category inline lib::error_code make_error_code(error::processor_errors e) { return lib::error_code(static_cast(e), get_processor_category()); } /// Converts a processor error_code into a websocket close code /** * Looks up the appropriate WebSocket close code that should be sent after an * error of this sort occurred. * * If the error is not in the processor category close::status::blank is * returned. * * If the error isn't normally associated with reasons to close a connection * (such as errors intended to be used internally or delivered to client * applications, ex: invalid arguments) then * close::status::internal_endpoint_error is returned. */ inline close::status::value to_ws(lib::error_code ec) { if (ec.category() != get_processor_category()) { return close::status::blank; } switch (ec.value()) { case error::protocol_violation: case error::control_too_big: case error::invalid_opcode: case error::invalid_rsv_bit: case error::fragmented_control: case error::invalid_continuation: case error::masking_required: case error::masking_forbidden: case error::reserved_close_code: case error::invalid_close_code: return close::status::protocol_error; case error::invalid_payload: case error::invalid_utf8: return close::status::invalid_payload; case error::message_too_big: return close::status::message_too_big; default: return close::status::internal_endpoint_error; } } } // namespace error } // namespace processor } // namespace websocketpp _WEBSOCKETPP_ERROR_CODE_ENUM_NS_START_ template<> struct is_error_code_enum { static bool const value = true; }; _WEBSOCKETPP_ERROR_CODE_ENUM_NS_END_ #endif //WEBSOCKETPP_PROCESSOR_BASE_HPP