28 #ifndef WEBSOCKETPP_PROCESSOR_HYBI13_HPP 29 #define WEBSOCKETPP_PROCESSOR_HYBI13_HPP 53 template <
typename config>
72 explicit hybi13(
bool secure,
bool p_is_server, msg_manager_ptr manager, rng_type& rng)
101 template <
typename header_type>
114 bool error = header.get_header_as_plist(
"Sec-WebSocket-Extensions",p);
126 http::parameter_list::const_iterator it;
129 err_str_pair neg_ret;
130 for (it = p.begin(); it != p.end(); ++it) {
132 if (it->first ==
"permessage-deflate") {
152 ret.second += neg_ret.second;
164 if (r.get_method() !=
"GET") {
168 if (r.get_version() !=
"HTTP/1.1") {
176 if (r.get_header(
"Sec-WebSocket-Key").empty()) {
180 return lib::error_code();
188 std::string
const & subprotocol, response_type & response)
const 190 std::string server_key = request.get_header(
"Sec-WebSocket-Key");
198 response.replace_header(
"Sec-WebSocket-Accept",server_key);
202 if (!subprotocol.empty()) {
203 response.replace_header(
"Sec-WebSocket-Protocol",subprotocol);
206 return lib::error_code();
216 uri, std::vector<std::string>
const & subprotocols)
const 218 req.set_method(
"GET");
219 req.set_uri(uri->get_resource());
220 req.set_version(
"HTTP/1.1");
222 req.append_header(
"Upgrade",
"websocket");
223 req.append_header(
"Connection",
"Upgrade");
224 req.replace_header(
"Sec-WebSocket-Version",
"13");
225 req.replace_header(
"Host",uri->get_host_port());
227 if (!subprotocols.empty()) {
228 std::ostringstream result;
229 std::vector<std::string>::const_iterator it = subprotocols.begin();
231 while (it != subprotocols.end()) {
232 result <<
", " << *it++;
235 req.replace_header(
"Sec-WebSocket-Protocol",result.str());
240 unsigned char raw_key[16];
242 for (
int i = 0; i < 4; i++) {
244 std::copy(conv.
c,conv.
c+4,&raw_key[i*4]);
247 req.replace_header(
"Sec-WebSocket-Key",
base64_encode(raw_key, 16));
251 if (!offer.empty()) {
252 req.replace_header(
"Sec-WebSocket-Extensions",offer);
256 return lib::error_code();
266 response_type& res)
const 274 std::string
const & upgrade_header = res.get_header(
"Upgrade");
282 std::string
const & con_header = res.get_header(
"Connection");
290 std::string key = req.get_header(
"Sec-WebSocket-Key");
293 if (ec || key != res.get_header(
"Sec-WebSocket-Accept")) {
299 return lib::error_code();
302 std::string
get_raw(response_type
const & res)
const {
306 std::string
const &
get_origin(request_type
const & r)
const {
307 return r.get_header(
"Origin");
311 std::vector<std::string> & subprotocol_list)
313 if (!req.get_header(
"Sec-WebSocket-Protocol").empty()) {
316 if (!req.get_header_as_plist(
"Sec-WebSocket-Protocol",p)) {
317 http::parameter_list::const_iterator it;
319 for (it = p.begin(); it != p.end(); ++it) {
320 subprotocol_list.push_back(it->first);
326 return lib::error_code();
360 size_t consume(uint8_t * buf,
size_t len, lib::error_code & ec) {
363 ec = lib::error_code();
458 if (bytes_to_process > 0) {
504 uint8_t trailer[4] = {0x00, 0x00, 0xff, 0xff};
523 return lib::error_code();
596 std::string& i = in->get_raw_payload();
597 std::string& o = out->get_raw_payload();
607 && in->get_compressed();
608 bool fin = in->get_fin();
628 o.resize(o.size()-4);
644 std::copy(i.begin(),i.end(),o.begin());
659 out->set_prepared(
true);
662 return lib::error_code();
666 lib::error_code
prepare_ping(std::string
const & in, message_ptr out)
const {
670 lib::error_code
prepare_pong(std::string
const & in, message_ptr out)
const {
675 std::string
const & reason, message_ptr out)
const 699 payload.resize(reason.size()+2);
701 payload[0] = val.
c[0];
702 payload[1] = val.
c[1];
704 std::copy(reason.begin(),reason.end(),payload.begin()+2);
714 unsigned char message_digest[20];
715 sha1::calc(key.c_str(),key.length(),message_digest);
718 return lib::error_code();
761 return bytes_to_read;
787 size_t offset = out.size();
800 out.append(reinterpret_cast<char *>(buf),len);
827 bool is_server,
bool new_msg)
const 890 return lib::error_code();
924 if (
sizeof(
size_t) == 4 && (payload_size >> 32)) {
928 return lib::error_code();
956 std::string
const & payload, message_ptr out)
const 975 std::string & o = out->get_raw_payload();
976 o.resize(payload.size());
988 std::copy(payload.begin(),payload.end(),o.begin());
992 out->set_prepared(
true);
994 return lib::error_code();
1056 #endif //WEBSOCKETPP_PROCESSOR_HYBI13_HPP bool is_control(value v)
Check if an opcode is for a control frame.
config::con_msg_manager_type msg_manager_type
bool invalid(value v)
Check if an opcode is invalid.
virtual lib::error_code prepare_data_frame(message_ptr in, message_ptr out)
Prepare a user data message for writing.
static uint8_t const payload_size_code_16bit
static char const connection_token[]
bool get_rsv1(basic_header const &h)
check whether the frame's RSV1 bit is set
uint16_t value
The type of a close code value.
config::message_type message_type
lib::error_code make_error_code(error::value e)
uri_ptr get_uri_from_host(request_type &request, std::string scheme)
Extract a URI ptr from the host header of the request.
bool get_rsv3(basic_header const &h)
check whether the frame's RSV3 bit is set
msg_metadata m_control_msg
bool ready() const
Test whether or not the processor has a message ready.
bool decode(iterator_type begin, iterator_type end)
Advance validator state with input from an iterator pair.
Clients may not send unmasked frames.
lib::error_code validate_handshake(request_type const &r) const
validate a WebSocket handshake request for this version
bool get_masked(basic_header const &h)
check whether the frame is masked
std::pair< lib::error_code, std::string > err_str_pair
void masked_copy(std::string const &i, std::string &o, frame::masking_key_type key) const
Copy and mask/unmask in one operation.
WebSocket protocol processor abstract base class.
size_t copy_extended_header_bytes(uint8_t const *buf, size_t len)
Reads bytes from buf into m_extended_header.
bool get_rsv2(basic_header const &h)
check whether the frame's RSV2 bit is set
bool has_permessage_deflate() const
lib::error_code process_handshake(request_type const &request, std::string const &subprotocol, response_type &response) const
Calculate the appropriate response for this websocket request.
Using a reason requires a close code.
Illegal use of reserved bit.
Provides streaming UTF8 validation functionality.
opcode::value get_opcode(basic_header const &h)
Extract opcode from basic header.
bool reserved(value code)
Test whether a close code is in a reserved range.
size_t process_payload_bytes(uint8_t *buf, size_t len, lib::error_code &ec)
Reads bytes from buf into message payload.
static uint8_t const payload_size_basic
Maximum size of a basic WebSocket payload.
std::vector< std::pair< std::string, attribute_list > > parameter_list
The type of an HTTP parameter list.
lib::error_code finalize_message()
Perform any finalization actions on an incoming message.
lib::error_code prepare_control(frame::opcode::value op, std::string const &payload, message_ptr out) const
Generic prepare control frame with opcode and payload.
masking_key_type get_masking_key(basic_header const &, extended_header const &)
Extract the masking key from a frame header.
static char const upgrade_token[]
bool get_error() const
Test whether or not the processor is in a fatal error state.
bool invalid(value code)
Test whether a close code is invalid on the wire.
Four byte conversion union.
Processor encountered invalid payload data.
void byte_mask(input_iter b, input_iter e, output_iter o, masking_key_type const &key, size_t key_offset=0)
Byte by byte mask/unmask.
std::string base64_encode(unsigned char const *input, size_t len)
Encode a char buffer into a base64 string.
std::string const & get_origin(request_type const &r) const
Return the value of the header containing the CORS origin.
size_t get_header_len(basic_header const &)
Calculates the full length of the header based on the first bytes.
std::string get_raw(response_type const &res) const
Given a completed response, get the raw bytes to put on the wire.
message_type::ptr message_ptr
Continuation without message.
Stores, parses, and manipulates HTTP responses.
err_str_pair negotiate_extensions_helper(header_type const &header)
Extension negotiation helper function.
Stub class for use when disabling permessage_deflate extension.
lib::error_code extract_subprotocols(request_type const &req, std::vector< std::string > &subprotocol_list)
Extracts requested subprotocols from a handshake request.
config::response_type response_type
lib::shared_ptr< message > ptr
Not supported on 32 bit systems.
Extension related operation was ignored because extensions are disabled.
message_ptr get_message()
Retrieves the most recently processed message.
err_str_pair negotiate_extensions(request_type const &request)
Initializes extensions based on the Sec-WebSocket-Extensions header.
frame::basic_header m_basic_header
bool validate(std::string const &s)
Validate a UTF8 string.
msg_metadata * m_current_msg
config::rng_type rng_type
size_t prepare_masking_key(masking_key_type const &key)
Extract a masking key into a value the size of a machine word.
config::request_type request_type
msg_manager_type::ptr msg_manager_ptr
lib::error_code make_error_code(error::processor_errors e)
Create an error code with the given value and the processor category.
static const bool enable_extensions
Global flag for enabling/disabling extensions.
Catch-all error for processor policy errors that don't fit in other categories.
msg_manager_ptr m_msg_manager
Thread safe stub "random" integer generator.
Reserved close code used.
uint8_t get_basic_size(basic_header const &)
Extracts the raw payload length specified in the basic header.
Namespace for the WebSocket++ project.
virtual lib::error_code prepare_close(close::status::value code, std::string const &reason, message_ptr out) const
Prepare a close frame.
uint64_t get_payload_size(basic_header const &, extended_header const &)
Extract the full payload size field from a WebSocket header.
static unsigned int const MAX_EXTENDED_HEADER_LENGTH
Maximum length of the variable portion of the WebSocket header.
Error parsing subprotocols.
Represents a buffer for a single WebSocket message.
size_t m_max_message_size
lib::error_code process_handshake_key(std::string &key) const
Convert a client handshake key into a server response key in place.
static char const handshake_guid[]
lib::error_code prepare_ping(std::string const &in, message_ptr out) const
Get URI.
lib::shared_ptr< uri > uri_ptr
Pointer to a URI.
permessage_deflate_type m_permessage_deflate
static uint8_t const payload_size_code_64bit
lib::error_code prepare_pong(std::string const &in, message_ptr out) const
Prepare a pong frame.
static value const no_status
A dummy value to indicate that no status code was received.
Servers may not send masked frames.
config::permessage_deflate_type permessage_deflate_type
Fragmented control message.
Processor encountered a message that was too large.
Error parsing extensions.
int get_version() const
Get the protocol version of this processor.
size_t copy_basic_header_bytes(uint8_t const *buf, size_t len)
Reads bytes from buf into m_basic_header.
lib::error_code validate_incoming_extended_header(frame::basic_header h, frame::extended_header e) const
Validate an incoming extended header.
size_t consume(uint8_t *buf, size_t len, lib::error_code &ec)
Process new websocket connection bytes.
lib::error_code client_handshake_request(request_type &req, uri_ptr uri, std::vector< std::string > const &subprotocols) const
Fill in a set of request headers for a client connection request.
Stores, parses, and manipulates HTTP requests.
std::string prepare_header(const basic_header &h, const extended_header &e)
Generate a properly sized contiguous string that encodes a full frame header.
lib::shared_ptr< con_msg_manager > ptr
static uint16_t const payload_size_extended
Maximum size of an extended WebSocket payload (basic payload = 126)
size_t byte_mask_circ(uint8_t *input, uint8_t *output, size_t length, size_t prepared_key)
Circular byte aligned mask/unmask.
Opcode was invalid for requested operation.
lib::error_code validate_incoming_basic_header(frame::basic_header const &h, bool is_server, bool new_msg) const
Validate an incoming basic header.
bool reserved(value v)
Check if an opcode is reserved.
bool get_fin(basic_header const &h)
Check whether the frame's FIN bit is set.
A connection message manager that allocates a new message for each request.
uri_ptr get_uri(request_type const &request) const
Extracts client uri from a handshake request.
size_t get_bytes_needed() const
Retrieves the number of bytes presently needed by the processor This value may be used as a hint to t...
hybi13(bool secure, bool p_is_server, msg_manager_ptr manager, rng_type &rng)
Processor for Hybi version 13 (RFC6455)
lib::error_code validate_server_handshake_response(request_type const &req, response_type &res) const
Validate the server's response to an outgoing handshake request.
Type used to convert close statuses between integer and wire representations.
static unsigned int const BASIC_HEADER_LENGTH
Minimum length of a WebSocket frame header.
T::const_iterator ci_find_substr(T const &haystack, T const &needle, std::locale const &loc=std::locale())
Find substring (case insensitive)
The processor method was called with invalid arguments.
void calc(void const *src, size_t bytelength, unsigned char *hash)
Calculate a SHA1 hash.
Payload length not minimally encoded.
err_str_pair negotiate_extensions(response_type const &response)
Initializes extensions based on the Sec-WebSocket-Extensions header.
bool complete()
Return whether the input sequence ended on a valid utf8 codepoint.
frame::extended_header m_extended_header