From d19ee815b831b78d726846e6185e6d4a4fda03f3 Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Wed, 21 Dec 2011 17:22:28 -0600 Subject: [PATCH] unfinished send api work --- src/messages/data.cpp | 32 +++++++++++++++++++++++++++++--- src/messages/data.hpp | 34 +++++++++++++++++++++++++++++++--- src/processors/hybi_header.cpp | 25 +++++++++++++++++++++++++ src/processors/hybi_header.hpp | 2 ++ 4 files changed, 87 insertions(+), 6 deletions(-) diff --git a/src/messages/data.cpp b/src/messages/data.cpp index 3bd7345c3d..70a7931a97 100644 --- a/src/messages/data.cpp +++ b/src/messages/data.cpp @@ -28,6 +28,7 @@ #include "data.hpp" #include "../processors/processor.hpp" +#include "../processors/hybi_header.hpp" using websocketpp::message::data; @@ -97,7 +98,7 @@ void data::process_character(unsigned char c) { void data::reset(frame::opcode::value opcode) { m_opcode = opcode; - m_masking_index = 0; + m_masking_index = M_NOT_MASKED; // -1 indicates do not mask/unmask m_payload.resize(0); m_validator.reset(); } @@ -112,5 +113,30 @@ void data::complete() { void data::set_masking_key(int32_t key) { *reinterpret_cast(m_masking_key) = key; - m_masking_index = (key == 0 ? -1 : 0); -} \ No newline at end of file + // -2 indicates a masked frame whose key is zero. + m_masking_index = (key == 0 ? M_MASK_KEY_ZERO : M_BYTE_0); +} + + +// This could be further optimized using methods that write directly into the +// m_payload buffer +void data::set_payload(const std::string& payload) { + m_payload.reserve(payload.size()); + std::copy(payload.begin(), payload.end(), m_payload.begin()); +} +void data::process() { + websocketpp::processor::hybi_header header; + header.set_fin(true); + header.set_opcode(m_opcode); + + // set opcode + // set + + // mask + if (m_masking_index >= 0) { + for (std::string::iterator it = m_payload.begin(); it != m_payload.end(); it++) { + (*it) = *it ^ m_masking_key[(m_masking_index++)%4]; + } + } +} + diff --git a/src/messages/data.hpp b/src/messages/data.hpp index bfeeb3fb3a..2db40afb06 100644 --- a/src/messages/data.hpp +++ b/src/messages/data.hpp @@ -41,18 +41,44 @@ class data { public: data(); + void reset(frame::opcode::value opcode); + frame::opcode::value get_opcode() const; const std::string& get_payload() const; + // ##reading## + // sets the masking key to be used to unmask as bytes are read. + void set_masking_key(int32_t key); + + // read at most size bytes from a payload stream and perform unmasking/utf8 + // validation. Returns number of bytes read. + // throws a processor::exception if the message is too big, there is a fatal + // istream read error, or invalid UTF8 data is read for a text message uint64_t process_payload(std::istream& input,uint64_t size); void process_character(unsigned char c); - void reset(frame::opcode::value opcode); void complete(); - void set_masking_key(int32_t key); + + // ##writing## + // sets the payload to payload. Performs max size and UTF8 validation + // immediately and throws processor::exception if it fails + void set_payload(const std::string& payload); + + // Performs masking and header generation if it has not been done already. + void process(); + private: static const uint64_t PAYLOAD_SIZE_INIT = 1000; // 1KB static const uint64_t PAYLOAD_SIZE_MAX = 100000000;// 100MB + enum index_value { + M_MASK_KEY_ZERO = -2, + M_NOT_MASKED = -1, + M_BYTE_0 = 0, + M_BYTE_1 = 1, + M_BYTE_2 = 2, + M_BYTE_3 = 3 + }; + // Message state frame::opcode::value m_opcode; @@ -61,9 +87,11 @@ private: // Masking state unsigned char m_masking_key[4]; - int m_masking_index; + // m_masking_index can take on + index_value m_masking_index; // Message buffers + std::string m_header; std::string m_payload; }; diff --git a/src/processors/hybi_header.cpp b/src/processors/hybi_header.cpp index d6138d8c63..690d024b38 100644 --- a/src/processors/hybi_header.cpp +++ b/src/processors/hybi_header.cpp @@ -199,6 +199,31 @@ size_t hybi_header::get_payload_size() const { return m_payload_size; } +void hybi_header::set_payload_size(size_t size) { + if (size <= frame::limits::PAYLOAD_SIZE_BASIC) { + // encode in byte 2 + m_header[1] &= (size & BPB1_PAYLOAD); + } else if (size <= frame::limits::PAYLOAD_SIZE_EXTENDED) { + // encode two byte + m_header[1] &= (BASIC_PAYLOAD_16BIT_CODE & BPB1_PAYLOAD); + + if (get_masked()) { + + } + + *(reinterpret_cast(&m_header[BASIC_HEADER_LENGTH])) = htons(size); + + + + + } else if (size <= frame::limits::PAYLOAD_SIZE_EXTENDED) { + // encode two byte + m_header[1] &= (BASIC_PAYLOAD_64BIT_CODE & BPB1_PAYLOAD); + } else { + throw processor::exception("Client attempted to send a message that was too big",processor::error::MESSAGE_TOO_BIG); + } +} + bool hybi_header::is_control() const { return (frame::opcode::is_control(get_opcode())); } diff --git a/src/processors/hybi_header.hpp b/src/processors/hybi_header.hpp index 60ea52240c..f9fd789c8b 100644 --- a/src/processors/hybi_header.hpp +++ b/src/processors/hybi_header.hpp @@ -72,6 +72,8 @@ public: uint8_t get_basic_size() const; size_t get_payload_size() const; + void set_payload_size(size_t size); + bool is_control() const; void process_basic_header();