mirror of
https://github.com/VCMP-SqMod/SqMod.git
synced 2025-12-20 06:57:19 +01:00
Initial preparations for CURL and Discord integration.
This commit is contained in:
299
module/Vendor/WebSocketPP/websocketpp/processors/base.hpp
vendored
Normal file
299
module/Vendor/WebSocketPP/websocketpp/processors/base.hpp
vendored
Normal file
@@ -0,0 +1,299 @@
|
||||
/*
|
||||
* 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 <websocketpp/close.hpp>
|
||||
#include <websocketpp/utilities.hpp>
|
||||
#include <websocketpp/uri.hpp>
|
||||
|
||||
#include <websocketpp/common/cpp11.hpp>
|
||||
#include <websocketpp/common/system_error.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
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<int>(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<websocketpp::processor::error::processor_errors>
|
||||
{
|
||||
static bool const value = true;
|
||||
};
|
||||
_WEBSOCKETPP_ERROR_CODE_ENUM_NS_END_
|
||||
|
||||
#endif //WEBSOCKETPP_PROCESSOR_BASE_HPP
|
||||
462
module/Vendor/WebSocketPP/websocketpp/processors/hybi00.hpp
vendored
Normal file
462
module/Vendor/WebSocketPP/websocketpp/processors/hybi00.hpp
vendored
Normal file
@@ -0,0 +1,462 @@
|
||||
/*
|
||||
* 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_HYBI00_HPP
|
||||
#define WEBSOCKETPP_PROCESSOR_HYBI00_HPP
|
||||
|
||||
#include <websocketpp/frame.hpp>
|
||||
#include <websocketpp/http/constants.hpp>
|
||||
|
||||
#include <websocketpp/utf8_validator.hpp>
|
||||
#include <websocketpp/common/network.hpp>
|
||||
#include <websocketpp/common/md5.hpp>
|
||||
#include <websocketpp/common/platforms.hpp>
|
||||
|
||||
#include <websocketpp/processors/processor.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace websocketpp {
|
||||
namespace processor {
|
||||
|
||||
/// Processor for Hybi Draft version 00
|
||||
/**
|
||||
* There are many differences between Hybi 00 and Hybi 13
|
||||
*/
|
||||
template <typename config>
|
||||
class hybi00 : public processor<config> {
|
||||
public:
|
||||
typedef processor<config> base;
|
||||
|
||||
typedef typename config::request_type request_type;
|
||||
typedef typename config::response_type response_type;
|
||||
|
||||
typedef typename config::message_type message_type;
|
||||
typedef typename message_type::ptr message_ptr;
|
||||
|
||||
typedef typename config::con_msg_manager_type::ptr msg_manager_ptr;
|
||||
|
||||
explicit hybi00(bool secure, bool p_is_server, msg_manager_ptr manager)
|
||||
: processor<config>(secure, p_is_server)
|
||||
, msg_hdr(0x00)
|
||||
, msg_ftr(0xff)
|
||||
, m_state(HEADER)
|
||||
, m_msg_manager(manager) {}
|
||||
|
||||
int get_version() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
lib::error_code validate_handshake(request_type const & r) const {
|
||||
if (r.get_method() != "GET") {
|
||||
return make_error_code(error::invalid_http_method);
|
||||
}
|
||||
|
||||
if (r.get_version() != "HTTP/1.1") {
|
||||
return make_error_code(error::invalid_http_version);
|
||||
}
|
||||
|
||||
// required headers
|
||||
// Host is required by HTTP/1.1
|
||||
// Connection is required by is_websocket_handshake
|
||||
// Upgrade is required by is_websocket_handshake
|
||||
if (r.get_header("Sec-WebSocket-Key1").empty() ||
|
||||
r.get_header("Sec-WebSocket-Key2").empty() ||
|
||||
r.get_header("Sec-WebSocket-Key3").empty())
|
||||
{
|
||||
return make_error_code(error::missing_required_header);
|
||||
}
|
||||
|
||||
return lib::error_code();
|
||||
}
|
||||
|
||||
lib::error_code process_handshake(request_type const & req,
|
||||
std::string const & subprotocol, response_type & res) const
|
||||
{
|
||||
char key_final[16];
|
||||
|
||||
// copy key1 into final key
|
||||
decode_client_key(req.get_header("Sec-WebSocket-Key1"), &key_final[0]);
|
||||
|
||||
// copy key2 into final key
|
||||
decode_client_key(req.get_header("Sec-WebSocket-Key2"), &key_final[4]);
|
||||
|
||||
// copy key3 into final key
|
||||
// key3 should be exactly 8 bytes. If it is more it will be truncated
|
||||
// if it is less the final key will almost certainly be wrong.
|
||||
// TODO: decide if it is best to silently fail here or produce some sort
|
||||
// of warning or exception.
|
||||
std::string const & key3 = req.get_header("Sec-WebSocket-Key3");
|
||||
std::copy(key3.c_str(),
|
||||
key3.c_str()+(std::min)(static_cast<size_t>(8), key3.size()),
|
||||
&key_final[8]);
|
||||
|
||||
res.append_header(
|
||||
"Sec-WebSocket-Key3",
|
||||
md5::md5_hash_string(std::string(key_final,16))
|
||||
);
|
||||
|
||||
res.append_header("Upgrade","WebSocket");
|
||||
res.append_header("Connection","Upgrade");
|
||||
|
||||
// Echo back client's origin unless our local application set a
|
||||
// more restrictive one.
|
||||
if (res.get_header("Sec-WebSocket-Origin").empty()) {
|
||||
res.append_header("Sec-WebSocket-Origin",req.get_header("Origin"));
|
||||
}
|
||||
|
||||
// Echo back the client's request host unless our local application
|
||||
// set a different one.
|
||||
if (res.get_header("Sec-WebSocket-Location").empty()) {
|
||||
uri_ptr uri = get_uri(req);
|
||||
res.append_header("Sec-WebSocket-Location",uri->str());
|
||||
}
|
||||
|
||||
if (!subprotocol.empty()) {
|
||||
res.replace_header("Sec-WebSocket-Protocol",subprotocol);
|
||||
}
|
||||
|
||||
return lib::error_code();
|
||||
}
|
||||
|
||||
/// Fill in a set of request headers for a client connection request
|
||||
/**
|
||||
* The Hybi 00 processor only implements incoming connections so this will
|
||||
* always return an error.
|
||||
*
|
||||
* @param [out] req Set of headers to fill in
|
||||
* @param [in] uri The uri being connected to
|
||||
* @param [in] subprotocols The list of subprotocols to request
|
||||
*/
|
||||
lib::error_code client_handshake_request(request_type &, uri_ptr,
|
||||
std::vector<std::string> const &) const
|
||||
{
|
||||
return error::make_error_code(error::no_protocol_support);
|
||||
}
|
||||
|
||||
/// Validate the server's response to an outgoing handshake request
|
||||
/**
|
||||
* The Hybi 00 processor only implements incoming connections so this will
|
||||
* always return an error.
|
||||
*
|
||||
* @param req The original request sent
|
||||
* @param res The reponse to generate
|
||||
* @return An error code, 0 on success, non-zero for other errors
|
||||
*/
|
||||
lib::error_code validate_server_handshake_response(request_type const &,
|
||||
response_type &) const
|
||||
{
|
||||
return error::make_error_code(error::no_protocol_support);
|
||||
}
|
||||
|
||||
std::string get_raw(response_type const & res) const {
|
||||
response_type temp = res;
|
||||
temp.remove_header("Sec-WebSocket-Key3");
|
||||
return temp.raw() + res.get_header("Sec-WebSocket-Key3");
|
||||
}
|
||||
|
||||
std::string const & get_origin(request_type const & r) const {
|
||||
return r.get_header("Origin");
|
||||
}
|
||||
|
||||
/// Extracts requested subprotocols from a handshake request
|
||||
/**
|
||||
* hybi00 does support subprotocols
|
||||
* https://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-00#section-1.9
|
||||
*
|
||||
* @param [in] req The request to extract from
|
||||
* @param [out] subprotocol_list A reference to a vector of strings to store
|
||||
* the results in.
|
||||
*/
|
||||
lib::error_code extract_subprotocols(request_type const & req,
|
||||
std::vector<std::string> & subprotocol_list)
|
||||
{
|
||||
if (!req.get_header("Sec-WebSocket-Protocol").empty()) {
|
||||
http::parameter_list p;
|
||||
|
||||
if (!req.get_header_as_plist("Sec-WebSocket-Protocol",p)) {
|
||||
http::parameter_list::const_iterator it;
|
||||
|
||||
for (it = p.begin(); it != p.end(); ++it) {
|
||||
subprotocol_list.push_back(it->first);
|
||||
}
|
||||
} else {
|
||||
return error::make_error_code(error::subprotocol_parse_error);
|
||||
}
|
||||
}
|
||||
return lib::error_code();
|
||||
}
|
||||
|
||||
uri_ptr get_uri(request_type const & request) const {
|
||||
std::string h = request.get_header("Host");
|
||||
|
||||
size_t last_colon = h.rfind(":");
|
||||
size_t last_sbrace = h.rfind("]");
|
||||
|
||||
// no : = hostname with no port
|
||||
// last : before ] = ipv6 literal with no port
|
||||
// : with no ] = hostname with port
|
||||
// : after ] = ipv6 literal with port
|
||||
|
||||
if (last_colon == std::string::npos ||
|
||||
(last_sbrace != std::string::npos && last_sbrace > last_colon))
|
||||
{
|
||||
return lib::make_shared<uri>(base::m_secure, h, request.get_uri());
|
||||
} else {
|
||||
return lib::make_shared<uri>(base::m_secure,
|
||||
h.substr(0,last_colon),
|
||||
h.substr(last_colon+1),
|
||||
request.get_uri());
|
||||
}
|
||||
|
||||
// TODO: check if get_uri is a full uri
|
||||
}
|
||||
|
||||
/// Get hybi00 handshake key3
|
||||
/**
|
||||
* @todo This doesn't appear to be used anymore. It might be able to be
|
||||
* removed
|
||||
*/
|
||||
std::string get_key3() const {
|
||||
return "";
|
||||
}
|
||||
|
||||
/// Process new websocket connection bytes
|
||||
size_t consume(uint8_t * buf, size_t len, lib::error_code & ec) {
|
||||
// if in state header we are expecting a 0x00 byte, if we don't get one
|
||||
// it is a fatal error
|
||||
size_t p = 0; // bytes processed
|
||||
size_t l = 0;
|
||||
|
||||
ec = lib::error_code();
|
||||
|
||||
while (p < len) {
|
||||
if (m_state == HEADER) {
|
||||
if (buf[p] == msg_hdr) {
|
||||
p++;
|
||||
m_msg_ptr = m_msg_manager->get_message(frame::opcode::text,1);
|
||||
|
||||
if (!m_msg_ptr) {
|
||||
ec = make_error_code(websocketpp::error::no_incoming_buffers);
|
||||
m_state = FATAL_ERROR;
|
||||
} else {
|
||||
m_state = PAYLOAD;
|
||||
}
|
||||
} else {
|
||||
ec = make_error_code(error::protocol_violation);
|
||||
m_state = FATAL_ERROR;
|
||||
}
|
||||
} else if (m_state == PAYLOAD) {
|
||||
uint8_t *it = std::find(buf+p,buf+len,msg_ftr);
|
||||
|
||||
// 0 1 2 3 4 5
|
||||
// 0x00 0x23 0x23 0x23 0xff 0xXX
|
||||
|
||||
// Copy payload bytes into message
|
||||
l = static_cast<size_t>(it-(buf+p));
|
||||
m_msg_ptr->append_payload(buf+p,l);
|
||||
p += l;
|
||||
|
||||
if (it != buf+len) {
|
||||
// message is done, copy it and the trailing
|
||||
p++;
|
||||
// TODO: validation
|
||||
m_state = READY;
|
||||
}
|
||||
} else {
|
||||
// TODO
|
||||
break;
|
||||
}
|
||||
}
|
||||
// If we get one, we create a new message and move to application state
|
||||
|
||||
// if in state application we are copying bytes into the output message
|
||||
// and validating them for UTF8 until we hit a 0xff byte. Once we hit
|
||||
// 0x00, the message is complete and is dispatched. Then we go back to
|
||||
// header state.
|
||||
|
||||
//ec = make_error_code(error::not_implemented);
|
||||
return p;
|
||||
}
|
||||
|
||||
bool ready() const {
|
||||
return (m_state == READY);
|
||||
}
|
||||
|
||||
bool get_error() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
message_ptr get_message() {
|
||||
message_ptr ret = m_msg_ptr;
|
||||
m_msg_ptr = message_ptr();
|
||||
m_state = HEADER;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// Prepare a message for writing
|
||||
/**
|
||||
* Performs validation, masking, compression, etc. will return an error if
|
||||
* there was an error, otherwise msg will be ready to be written
|
||||
*/
|
||||
virtual lib::error_code prepare_data_frame(message_ptr in, message_ptr out)
|
||||
{
|
||||
if (!in || !out) {
|
||||
return make_error_code(error::invalid_arguments);
|
||||
}
|
||||
|
||||
// TODO: check if the message is prepared already
|
||||
|
||||
// validate opcode
|
||||
if (in->get_opcode() != frame::opcode::text) {
|
||||
return make_error_code(error::invalid_opcode);
|
||||
}
|
||||
|
||||
std::string& i = in->get_raw_payload();
|
||||
//std::string& o = out->get_raw_payload();
|
||||
|
||||
// validate payload utf8
|
||||
if (!utf8_validator::validate(i)) {
|
||||
return make_error_code(error::invalid_payload);
|
||||
}
|
||||
|
||||
// generate header
|
||||
out->set_header(std::string(reinterpret_cast<char const *>(&msg_hdr),1));
|
||||
|
||||
// process payload
|
||||
out->set_payload(i);
|
||||
out->append_payload(std::string(reinterpret_cast<char const *>(&msg_ftr),1));
|
||||
|
||||
// hybi00 doesn't support compression
|
||||
// hybi00 doesn't have masking
|
||||
|
||||
out->set_prepared(true);
|
||||
|
||||
return lib::error_code();
|
||||
}
|
||||
|
||||
/// Prepare a ping frame
|
||||
/**
|
||||
* Hybi 00 doesn't support pings so this will always return an error
|
||||
*
|
||||
* @param in The string to use for the ping payload
|
||||
* @param out The message buffer to prepare the ping in.
|
||||
* @return Status code, zero on success, non-zero on failure
|
||||
*/
|
||||
lib::error_code prepare_ping(std::string const &, message_ptr) const
|
||||
{
|
||||
return lib::error_code(error::no_protocol_support);
|
||||
}
|
||||
|
||||
/// Prepare a pong frame
|
||||
/**
|
||||
* Hybi 00 doesn't support pongs so this will always return an error
|
||||
*
|
||||
* @param in The string to use for the pong payload
|
||||
* @param out The message buffer to prepare the pong in.
|
||||
* @return Status code, zero on success, non-zero on failure
|
||||
*/
|
||||
lib::error_code prepare_pong(std::string const &, message_ptr) const
|
||||
{
|
||||
return lib::error_code(error::no_protocol_support);
|
||||
}
|
||||
|
||||
/// Prepare a close frame
|
||||
/**
|
||||
* Hybi 00 doesn't support the close code or reason so these parameters are
|
||||
* ignored.
|
||||
*
|
||||
* @param code The close code to send
|
||||
* @param reason The reason string to send
|
||||
* @param out The message buffer to prepare the fame in
|
||||
* @return Status code, zero on success, non-zero on failure
|
||||
*/
|
||||
lib::error_code prepare_close(close::status::value, std::string const &,
|
||||
message_ptr out) const
|
||||
{
|
||||
if (!out) {
|
||||
return lib::error_code(error::invalid_arguments);
|
||||
}
|
||||
|
||||
std::string val;
|
||||
val.append(1,'\xff');
|
||||
val.append(1,'\x00');
|
||||
out->set_payload(val);
|
||||
out->set_prepared(true);
|
||||
|
||||
return lib::error_code();
|
||||
}
|
||||
private:
|
||||
void decode_client_key(std::string const & key, char * result) const {
|
||||
unsigned int spaces = 0;
|
||||
std::string digits;
|
||||
uint32_t num;
|
||||
|
||||
// key2
|
||||
for (size_t i = 0; i < key.size(); i++) {
|
||||
if (key[i] == ' ') {
|
||||
spaces++;
|
||||
} else if (key[i] >= '0' && key[i] <= '9') {
|
||||
digits += key[i];
|
||||
}
|
||||
}
|
||||
|
||||
num = static_cast<uint32_t>(strtoul(digits.c_str(), NULL, 10));
|
||||
if (spaces > 0 && num > 0) {
|
||||
num = htonl(num/spaces);
|
||||
std::copy(reinterpret_cast<char*>(&num),
|
||||
reinterpret_cast<char*>(&num)+4,
|
||||
result);
|
||||
} else {
|
||||
std::fill(result,result+4,0);
|
||||
}
|
||||
}
|
||||
|
||||
enum state {
|
||||
HEADER = 0,
|
||||
PAYLOAD = 1,
|
||||
READY = 2,
|
||||
FATAL_ERROR = 3
|
||||
};
|
||||
|
||||
uint8_t const msg_hdr;
|
||||
uint8_t const msg_ftr;
|
||||
|
||||
state m_state;
|
||||
|
||||
msg_manager_ptr m_msg_manager;
|
||||
message_ptr m_msg_ptr;
|
||||
utf8_validator::validator m_validator;
|
||||
};
|
||||
|
||||
} // namespace processor
|
||||
} // namespace websocketpp
|
||||
|
||||
#endif //WEBSOCKETPP_PROCESSOR_HYBI00_HPP
|
||||
78
module/Vendor/WebSocketPP/websocketpp/processors/hybi07.hpp
vendored
Normal file
78
module/Vendor/WebSocketPP/websocketpp/processors/hybi07.hpp
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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_HYBI07_HPP
|
||||
#define WEBSOCKETPP_PROCESSOR_HYBI07_HPP
|
||||
|
||||
#include <websocketpp/processors/hybi08.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace websocketpp {
|
||||
namespace processor {
|
||||
|
||||
/// Processor for Hybi Draft version 07
|
||||
/**
|
||||
* The primary difference between 07 and 08 is a version number.
|
||||
*/
|
||||
template <typename config>
|
||||
class hybi07 : public hybi08<config> {
|
||||
public:
|
||||
typedef typename config::request_type request_type;
|
||||
|
||||
typedef typename config::con_msg_manager_type::ptr msg_manager_ptr;
|
||||
typedef typename config::rng_type rng_type;
|
||||
|
||||
explicit hybi07(bool secure, bool p_is_server, msg_manager_ptr manager, rng_type& rng)
|
||||
: hybi08<config>(secure, p_is_server, manager, rng) {}
|
||||
|
||||
/// Fill in a set of request headers for a client connection request
|
||||
/**
|
||||
* The Hybi 07 processor only implements incoming connections so this will
|
||||
* always return an error.
|
||||
*
|
||||
* @param [out] req Set of headers to fill in
|
||||
* @param [in] uri The uri being connected to
|
||||
* @param [in] subprotocols The list of subprotocols to request
|
||||
*/
|
||||
lib::error_code client_handshake_request(request_type &, uri_ptr,
|
||||
std::vector<std::string> const &) const
|
||||
{
|
||||
return error::make_error_code(error::no_protocol_support);
|
||||
}
|
||||
|
||||
int get_version() const {
|
||||
return 7;
|
||||
}
|
||||
private:
|
||||
};
|
||||
|
||||
} // namespace processor
|
||||
} // namespace websocketpp
|
||||
|
||||
#endif //WEBSOCKETPP_PROCESSOR_HYBI07_HPP
|
||||
83
module/Vendor/WebSocketPP/websocketpp/processors/hybi08.hpp
vendored
Normal file
83
module/Vendor/WebSocketPP/websocketpp/processors/hybi08.hpp
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* 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_HYBI08_HPP
|
||||
#define WEBSOCKETPP_PROCESSOR_HYBI08_HPP
|
||||
|
||||
#include <websocketpp/processors/hybi13.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace websocketpp {
|
||||
namespace processor {
|
||||
|
||||
/// Processor for Hybi Draft version 08
|
||||
/**
|
||||
* The primary difference between 08 and 13 is a different origin header name
|
||||
*/
|
||||
template <typename config>
|
||||
class hybi08 : public hybi13<config> {
|
||||
public:
|
||||
typedef hybi08<config> type;
|
||||
typedef typename config::request_type request_type;
|
||||
|
||||
typedef typename config::con_msg_manager_type::ptr msg_manager_ptr;
|
||||
typedef typename config::rng_type rng_type;
|
||||
|
||||
explicit hybi08(bool secure, bool p_is_server, msg_manager_ptr manager, rng_type& rng)
|
||||
: hybi13<config>(secure, p_is_server, manager, rng) {}
|
||||
|
||||
/// Fill in a set of request headers for a client connection request
|
||||
/**
|
||||
* The Hybi 08 processor only implements incoming connections so this will
|
||||
* always return an error.
|
||||
*
|
||||
* @param [out] req Set of headers to fill in
|
||||
* @param [in] uri The uri being connected to
|
||||
* @param [in] subprotocols The list of subprotocols to request
|
||||
*/
|
||||
lib::error_code client_handshake_request(request_type &, uri_ptr,
|
||||
std::vector<std::string> const &) const
|
||||
{
|
||||
return error::make_error_code(error::no_protocol_support);
|
||||
}
|
||||
|
||||
int get_version() const {
|
||||
return 8;
|
||||
}
|
||||
|
||||
std::string const & get_origin(request_type const & r) const {
|
||||
return r.get_header("Sec-WebSocket-Origin");
|
||||
}
|
||||
private:
|
||||
};
|
||||
|
||||
} // namespace processor
|
||||
} // namespace websocketpp
|
||||
|
||||
#endif //WEBSOCKETPP_PROCESSOR_HYBI08_HPP
|
||||
1078
module/Vendor/WebSocketPP/websocketpp/processors/hybi13.hpp
vendored
Normal file
1078
module/Vendor/WebSocketPP/websocketpp/processors/hybi13.hpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
407
module/Vendor/WebSocketPP/websocketpp/processors/processor.hpp
vendored
Normal file
407
module/Vendor/WebSocketPP/websocketpp/processors/processor.hpp
vendored
Normal file
@@ -0,0 +1,407 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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_HPP
|
||||
#define WEBSOCKETPP_PROCESSOR_HPP
|
||||
|
||||
#include <websocketpp/processors/base.hpp>
|
||||
#include <websocketpp/common/system_error.hpp>
|
||||
|
||||
#include <websocketpp/close.hpp>
|
||||
#include <websocketpp/utilities.hpp>
|
||||
#include <websocketpp/uri.hpp>
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace websocketpp {
|
||||
/// Processors encapsulate the protocol rules specific to each WebSocket version
|
||||
/**
|
||||
* The processors namespace includes a number of free functions that operate on
|
||||
* various WebSocket related data structures and perform processing that is not
|
||||
* related to specific versions of the protocol.
|
||||
*
|
||||
* It also includes the abstract interface for the protocol specific processing
|
||||
* engines. These engines wrap all of the logic necessary for parsing and
|
||||
* validating WebSocket handshakes and messages of specific protocol version
|
||||
* and set of allowed extensions.
|
||||
*
|
||||
* An instance of a processor represents the state of a single WebSocket
|
||||
* connection of the associated version. One processor instance is needed per
|
||||
* logical WebSocket connection.
|
||||
*/
|
||||
namespace processor {
|
||||
|
||||
/// Determine whether or not a generic HTTP request is a WebSocket handshake
|
||||
/**
|
||||
* @param r The HTTP request to read.
|
||||
*
|
||||
* @return True if the request is a WebSocket handshake, false otherwise
|
||||
*/
|
||||
template <typename request_type>
|
||||
bool is_websocket_handshake(request_type& r) {
|
||||
using utility::ci_find_substr;
|
||||
|
||||
std::string const & upgrade_header = r.get_header("Upgrade");
|
||||
|
||||
if (ci_find_substr(upgrade_header, constants::upgrade_token,
|
||||
sizeof(constants::upgrade_token)-1) == upgrade_header.end())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string const & con_header = r.get_header("Connection");
|
||||
|
||||
if (ci_find_substr(con_header, constants::connection_token,
|
||||
sizeof(constants::connection_token)-1) == con_header.end())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Extract the version from a WebSocket handshake request
|
||||
/**
|
||||
* A blank version header indicates a spec before versions were introduced.
|
||||
* The only such versions in shipping products are Hixie Draft 75 and Hixie
|
||||
* Draft 76. Draft 75 is present in Chrome 4-5 and Safari 5.0.0, Draft 76 (also
|
||||
* known as hybi 00 is present in Chrome 6-13 and Safari 5.0.1+. As
|
||||
* differentiating between these two sets of browsers is very difficult and
|
||||
* Safari 5.0.1+ accounts for the vast majority of cases in the wild this
|
||||
* function assumes that all handshakes without a valid version header are
|
||||
* Hybi 00.
|
||||
*
|
||||
* @param r The WebSocket handshake request to read.
|
||||
*
|
||||
* @return The WebSocket handshake version or -1 if there was an extraction
|
||||
* error.
|
||||
*/
|
||||
template <typename request_type>
|
||||
int get_websocket_version(request_type& r) {
|
||||
if (!r.ready()) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (r.get_header("Sec-WebSocket-Version").empty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int version;
|
||||
std::istringstream ss(r.get_header("Sec-WebSocket-Version"));
|
||||
|
||||
if ((ss >> version).fail()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
/// Extract a URI ptr from the host header of the request
|
||||
/**
|
||||
* @param request The request to extract the Host header from.
|
||||
*
|
||||
* @param scheme The scheme under which this request was received (ws, wss,
|
||||
* http, https, etc)
|
||||
*
|
||||
* @return A uri_pointer that encodes the value of the host header.
|
||||
*/
|
||||
template <typename request_type>
|
||||
uri_ptr get_uri_from_host(request_type & request, std::string scheme) {
|
||||
std::string h = request.get_header("Host");
|
||||
|
||||
size_t last_colon = h.rfind(":");
|
||||
size_t last_sbrace = h.rfind("]");
|
||||
|
||||
// no : = hostname with no port
|
||||
// last : before ] = ipv6 literal with no port
|
||||
// : with no ] = hostname with port
|
||||
// : after ] = ipv6 literal with port
|
||||
if (last_colon == std::string::npos ||
|
||||
(last_sbrace != std::string::npos && last_sbrace > last_colon))
|
||||
{
|
||||
return lib::make_shared<uri>(scheme, h, request.get_uri());
|
||||
} else {
|
||||
return lib::make_shared<uri>(scheme,
|
||||
h.substr(0,last_colon),
|
||||
h.substr(last_colon+1),
|
||||
request.get_uri());
|
||||
}
|
||||
}
|
||||
|
||||
/// WebSocket protocol processor abstract base class
|
||||
template <typename config>
|
||||
class processor {
|
||||
public:
|
||||
typedef processor<config> type;
|
||||
typedef typename config::request_type request_type;
|
||||
typedef typename config::response_type response_type;
|
||||
typedef typename config::message_type::ptr message_ptr;
|
||||
typedef std::pair<lib::error_code,std::string> err_str_pair;
|
||||
|
||||
explicit processor(bool secure, bool p_is_server)
|
||||
: m_secure(secure)
|
||||
, m_server(p_is_server)
|
||||
, m_max_message_size(config::max_message_size)
|
||||
{}
|
||||
|
||||
virtual ~processor() {}
|
||||
|
||||
/// Get the protocol version of this processor
|
||||
virtual int get_version() const = 0;
|
||||
|
||||
/// Get maximum message size
|
||||
/**
|
||||
* Get maximum message size. Maximum message size determines the point at which the
|
||||
* processor will fail a connection with the message_too_big protocol error.
|
||||
*
|
||||
* The default is retrieved from the max_message_size value from the template config
|
||||
*
|
||||
* @since 0.3.0
|
||||
*/
|
||||
size_t get_max_message_size() const {
|
||||
return m_max_message_size;
|
||||
}
|
||||
|
||||
/// Set maximum message size
|
||||
/**
|
||||
* Set maximum message size. Maximum message size determines the point at which the
|
||||
* processor will fail a connection with the message_too_big protocol error.
|
||||
*
|
||||
* The default is retrieved from the max_message_size value from the template config
|
||||
*
|
||||
* @since 0.3.0
|
||||
*
|
||||
* @param new_value The value to set as the maximum message size.
|
||||
*/
|
||||
void set_max_message_size(size_t new_value) {
|
||||
m_max_message_size = new_value;
|
||||
}
|
||||
|
||||
/// Returns whether or not the permessage_compress extension is implemented
|
||||
/**
|
||||
* Compile time flag that indicates whether this processor has implemented
|
||||
* the permessage_compress extension. By default this is false.
|
||||
*/
|
||||
virtual bool has_permessage_compress() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Initializes extensions based on the Sec-WebSocket-Extensions header
|
||||
/**
|
||||
* Reads the Sec-WebSocket-Extensions header and determines if any of the
|
||||
* requested extensions are supported by this processor. If they are their
|
||||
* settings data is initialized and an extension string to send to the
|
||||
* is returned.
|
||||
*
|
||||
* @param request The request or response headers to look at.
|
||||
*/
|
||||
virtual err_str_pair negotiate_extensions(request_type const &) {
|
||||
return err_str_pair();
|
||||
}
|
||||
|
||||
/// Initializes extensions based on the Sec-WebSocket-Extensions header
|
||||
/**
|
||||
* Reads the Sec-WebSocket-Extensions header and determines if any of the
|
||||
* requested extensions were accepted by the server. If they are their
|
||||
* settings data is initialized. If they are not a list of required
|
||||
* extensions (if any) is returned. This list may be sent back to the server
|
||||
* as a part of the 1010/Extension required close code.
|
||||
*
|
||||
* @param response The request or response headers to look at.
|
||||
*/
|
||||
virtual err_str_pair negotiate_extensions(response_type const &) {
|
||||
return err_str_pair();
|
||||
}
|
||||
|
||||
/// validate a WebSocket handshake request for this version
|
||||
/**
|
||||
* @param request The WebSocket handshake request to validate.
|
||||
* is_websocket_handshake(request) must be true and
|
||||
* get_websocket_version(request) must equal this->get_version().
|
||||
*
|
||||
* @return A status code, 0 on success, non-zero for specific sorts of
|
||||
* failure
|
||||
*/
|
||||
virtual lib::error_code validate_handshake(request_type const & request) const = 0;
|
||||
|
||||
/// Calculate the appropriate response for this websocket request
|
||||
/**
|
||||
* @param req The request to process
|
||||
*
|
||||
* @param subprotocol The subprotocol in use
|
||||
*
|
||||
* @param res The response to store the processed response in
|
||||
*
|
||||
* @return An error code, 0 on success, non-zero for other errors
|
||||
*/
|
||||
virtual lib::error_code process_handshake(request_type const & req,
|
||||
std::string const & subprotocol, response_type& res) const = 0;
|
||||
|
||||
/// Fill in an HTTP request for an outgoing connection handshake
|
||||
/**
|
||||
* @param req The request to process.
|
||||
*
|
||||
* @return An error code, 0 on success, non-zero for other errors
|
||||
*/
|
||||
virtual lib::error_code client_handshake_request(request_type & req,
|
||||
uri_ptr uri, std::vector<std::string> const & subprotocols) const = 0;
|
||||
|
||||
/// Validate the server's response to an outgoing handshake request
|
||||
/**
|
||||
* @param req The original request sent
|
||||
* @param res The reponse to generate
|
||||
* @return An error code, 0 on success, non-zero for other errors
|
||||
*/
|
||||
virtual lib::error_code validate_server_handshake_response(request_type
|
||||
const & req, response_type & res) const = 0;
|
||||
|
||||
/// Given a completed response, get the raw bytes to put on the wire
|
||||
virtual std::string get_raw(response_type const & request) const = 0;
|
||||
|
||||
/// Return the value of the header containing the CORS origin.
|
||||
virtual std::string const & get_origin(request_type const & request) const = 0;
|
||||
|
||||
/// Extracts requested subprotocols from a handshake request
|
||||
/**
|
||||
* Extracts a list of all subprotocols that the client has requested in the
|
||||
* given opening handshake request.
|
||||
*
|
||||
* @param [in] req The request to extract from
|
||||
* @param [out] subprotocol_list A reference to a vector of strings to store
|
||||
* the results in.
|
||||
*/
|
||||
virtual lib::error_code extract_subprotocols(const request_type & req,
|
||||
std::vector<std::string> & subprotocol_list) = 0;
|
||||
|
||||
/// Extracts client uri from a handshake request
|
||||
virtual uri_ptr get_uri(request_type const & request) const = 0;
|
||||
|
||||
/// process new websocket connection bytes
|
||||
/**
|
||||
* WebSocket connections are a continous stream of bytes that must be
|
||||
* interpreted by a protocol processor into discrete frames.
|
||||
*
|
||||
* @param buf Buffer from which bytes should be read.
|
||||
* @param len Length of buffer
|
||||
* @param ec Reference to an error code to return any errors in
|
||||
* @return Number of bytes processed
|
||||
*/
|
||||
virtual size_t consume(uint8_t *buf, size_t len, lib::error_code & ec) = 0;
|
||||
|
||||
/// Checks if there is a message ready
|
||||
/**
|
||||
* Checks if the most recent consume operation processed enough bytes to
|
||||
* complete a new WebSocket message. The message can be retrieved by calling
|
||||
* get_message() which will reset the internal state to not-ready and allow
|
||||
* consume to read more bytes.
|
||||
*
|
||||
* @return Whether or not a message is ready.
|
||||
*/
|
||||
virtual bool ready() const = 0;
|
||||
|
||||
/// Retrieves the most recently processed message
|
||||
/**
|
||||
* Retrieves a shared pointer to the recently completed message if there is
|
||||
* one. If ready() returns true then there is a message available.
|
||||
* Retrieving the message with get_message will reset the state of ready.
|
||||
* As such, each new message may be retrieved only once. Calling get_message
|
||||
* when there is no message available will result in a null pointer being
|
||||
* returned.
|
||||
*
|
||||
* @return A pointer to the most recently processed message or a null shared
|
||||
* pointer.
|
||||
*/
|
||||
virtual message_ptr get_message() = 0;
|
||||
|
||||
/// Tests whether the processor is in a fatal error state
|
||||
virtual bool get_error() const = 0;
|
||||
|
||||
/// Retrieves the number of bytes presently needed by the processor
|
||||
/// This value may be used as a hint to the transport layer as to how many
|
||||
/// bytes to wait for before running consume again.
|
||||
virtual size_t get_bytes_needed() const {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/// Prepare a data message for writing
|
||||
/**
|
||||
* Performs validation, masking, compression, etc. will return an error if
|
||||
* there was an error, otherwise msg will be ready to be written
|
||||
*/
|
||||
virtual lib::error_code prepare_data_frame(message_ptr in, message_ptr out) = 0;
|
||||
|
||||
/// Prepare a ping frame
|
||||
/**
|
||||
* Ping preparation is entirely state free. There is no payload validation
|
||||
* other than length. Payload need not be UTF-8.
|
||||
*
|
||||
* @param in The string to use for the ping payload
|
||||
* @param out The message buffer to prepare the ping in.
|
||||
* @return Status code, zero on success, non-zero on failure
|
||||
*/
|
||||
virtual lib::error_code prepare_ping(std::string const & in, message_ptr out) const
|
||||
= 0;
|
||||
|
||||
/// Prepare a pong frame
|
||||
/**
|
||||
* Pong preparation is entirely state free. There is no payload validation
|
||||
* other than length. Payload need not be UTF-8.
|
||||
*
|
||||
* @param in The string to use for the pong payload
|
||||
* @param out The message buffer to prepare the pong in.
|
||||
* @return Status code, zero on success, non-zero on failure
|
||||
*/
|
||||
virtual lib::error_code prepare_pong(std::string const & in, message_ptr out) const
|
||||
= 0;
|
||||
|
||||
/// Prepare a close frame
|
||||
/**
|
||||
* Close preparation is entirely state free. The code and reason are both
|
||||
* subject to validation. Reason must be valid UTF-8. Code must be a valid
|
||||
* un-reserved WebSocket close code. Use close::status::no_status to
|
||||
* indicate no code. If no code is supplied a reason may not be specified.
|
||||
*
|
||||
* @param code The close code to send
|
||||
* @param reason The reason string to send
|
||||
* @param out The message buffer to prepare the fame in
|
||||
* @return Status code, zero on success, non-zero on failure
|
||||
*/
|
||||
virtual lib::error_code prepare_close(close::status::value code,
|
||||
std::string const & reason, message_ptr out) const = 0;
|
||||
protected:
|
||||
bool const m_secure;
|
||||
bool const m_server;
|
||||
size_t m_max_message_size;
|
||||
};
|
||||
|
||||
} // namespace processor
|
||||
} // namespace websocketpp
|
||||
|
||||
#endif //WEBSOCKETPP_PROCESSOR_HPP
|
||||
Reference in New Issue
Block a user