From e9b667da26bef0d82bdc3694b0c9fe9bfe95dacd Mon Sep 17 00:00:00 2001 From: Saturneric Date: Thu, 11 Mar 2021 16:06:57 +0800 Subject: [PATCH] Modified --- include/communicate/message.h | 21 +++++++++- src/communicate/.message_parser.cpp.swo | Bin 0 -> 20480 bytes src/communicate/message_factory.cpp | 51 +++++++++++++++++++++++ src/communicate/message_parser.cpp | 11 +++++ test/test_commu_modules/test_message.cpp | 7 +++- 5 files changed, 86 insertions(+), 4 deletions(-) create mode 100644 src/communicate/.message_parser.cpp.swo diff --git a/include/communicate/message.h b/include/communicate/message.h index 76e3eb6..411fb9f 100644 --- a/include/communicate/message.h +++ b/include/communicate/message.h @@ -15,6 +15,7 @@ using std::queue; namespace Net { +// the structure to store the option part of a message class Option { public: Option(const string &key, const string &value); @@ -34,6 +35,7 @@ public: void updateValue(const string &value); private: + // the key is unique within a message shared_ptr key; shared_ptr value; }; @@ -105,30 +107,45 @@ private: ssize_t decode_tail(const vector &raw_Data, size_t offset, Message &msg); + void calculate_options_hash(const vector &raw_data, int32_t end_index, int16_t &sum_hash); + SHA256Generator sign_gen; }; class MessageParser { public: - + + // send a received buffer to parse void parse(const void *buf, size_t size); + // Get a parsed message from the queue shared_ptr getMessage(); + // Get the count of the parsed meaasge size_t getMessageCount(); private: + + // state recorder of a special part of a message int head_state = -5; int option_state = -4; ssize_t body_state = -1; int tail_state = -4; + + // factory used to read data and form the message step by step MessageFactory factory; + + // store the message parsed queue> msgs; + // buffer to store the data give by queue buffer; + // buffer to temporarily store the data of the certain part related to the state of the parser vector temp_buffer; + // temporarily record the message concentrated shared_ptr temp_msg; - + + // reset all state and refresh the parser void reset_state(); void locate_head(); diff --git a/src/communicate/.message_parser.cpp.swo b/src/communicate/.message_parser.cpp.swo new file mode 100644 index 0000000000000000000000000000000000000000..91e2ceb69505ee203f9ee2e18c7319c154626e94 GIT binary patch literal 20480 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 +#include namespace Net { @@ -24,18 +25,21 @@ void MessageFactory::encode_head(const Message &msg, vector &raw_data) { raw_data.push_back(' '); + // 协议版本 const string s_version = std::to_string(msg.version); raw_data.insert(raw_data.end(), s_version.cbegin(), s_version.cend()); raw_data.push_back(' '); + // 消息类型 const string s_type = std::to_string(msg.type); raw_data.insert(raw_data.end(), s_type.cbegin(), s_type.cend()); raw_data.push_back(' '); + // 会话ID const string s_tid = std::to_string(msg.tid); raw_data.insert(raw_data.end(), s_tid.cbegin(), s_tid.cend()); @@ -67,6 +71,16 @@ void MessageFactory::encode_options(const Message &msg, raw_data.push_back('\n'); } + // 计算头部和配置部分的哈希值 + int16_t sum_hash; + + calculate_options_hash(raw_data, raw_data.size() - 1, sum_hash); + const string sum_hash_str = std::to_string(sum_hash); + raw_data.insert(raw_data.end(), sum_hash_str.cbegin(), sum_hash_str.cend()); + + raw_data.push_back('\r'); + raw_data.push_back('\n'); + raw_data.push_back('\r'); raw_data.push_back('\n'); } @@ -158,8 +172,26 @@ ssize_t MessageFactory::decode_options(const vector &raw_data, msg.addOption(key.c_str(), value.c_str()); } + int sum_hash_range = index - 2; + --index; + string sum_hash_str; + while((c = raw_data[index++]) != '\r') { + sum_hash_str.push_back(c); + } + + if(raw_data[index++] != '\n') { + return -1; + } + + int16_t sum_hash = std::stoi(sum_hash_str); + int16_t sum_hash_check; + + calculate_options_hash(raw_data, sum_hash_range, sum_hash_check); + + if(sum_hash_check != sum_hash) return -1; + if (raw_data[index++] != '\r' || raw_data[index++] != '\n') return -1; @@ -200,6 +232,24 @@ ssize_t MessageFactory::decode_tail(const vector &raw_data, size_t offset, return index; } +void MessageFactory::calculate_options_hash(const vector &raw_data, int32_t end_index, int16_t &sum_hash) { + + if(end_index > raw_data.size()) { + throw std::runtime_error("end index out of range"); + } + + sum_hash = 0; + + int32_t index = 0; + + for(auto &c : raw_data) { + sum_hash += static_cast(c); + sum_hash %= 65535; + if (index++ >= end_index) break; + } + +} + bool MessageFactory::decodeMessage(const vector &raw_data, Message &msg) { msg.clear(); @@ -251,4 +301,5 @@ bool MessageFactory::decodeMessageTail(const vector &raw_data, Message &ms if(!~decode_tail(raw_data, 0, msg)) return false; return true; } + } // namespace Net diff --git a/src/communicate/message_parser.cpp b/src/communicate/message_parser.cpp index ca3b21b..1682ba9 100644 --- a/src/communicate/message_parser.cpp +++ b/src/communicate/message_parser.cpp @@ -6,12 +6,16 @@ namespace Net { void MessageParser::parse(const void *buf, size_t size) { + // push all data in buff into queue named buffer const char *c_buf = (const char *)buf; for (int i = 0; i < size; i++) { buffer.push(c_buf[i]); } + // process the data byte by byte until the queue is empty while(!buffer.empty()) { + + // if there is no message concentrated then create new message if (temp_msg == nullptr) { temp_msg = std::make_shared(); } @@ -26,9 +30,12 @@ void MessageParser::parse(const void *buf, size_t size) { locate_tail(); } + // tail processing done if(!tail_state){ + // release the message concentrated msgs.push(temp_msg); temp_msg = nullptr; + // reset the state of the parser reset_state(); } } @@ -91,6 +98,8 @@ void MessageParser::locate_option() { option_state++; else if(c == '\r') option_state = -1; + else if (c > 47 && c < 58) + option_state++; continue; } if(option_state == -3) { @@ -219,8 +228,10 @@ void MessageParser::locate_tail() { void MessageParser::reset_state() { temp_buffer.clear(); + // reset the message concentrated if(temp_msg != nullptr) temp_msg->clear(); + // reset the state recorder head_state = -5; option_state = -4; body_state = -1; diff --git a/test/test_commu_modules/test_message.cpp b/test/test_commu_modules/test_message.cpp index 52d8f79..b510e03 100644 --- a/test/test_commu_modules/test_message.cpp +++ b/test/test_commu_modules/test_message.cpp @@ -26,6 +26,11 @@ TEST(Message_Test, base_test_1) { mf.encodeMessage(msg, rd); PrintTools::printInfoBuffer(rd, "Message Raw Data"); + for(auto &c : rd) { + printf("%c", c); + } + printf("\n"); + ASSERT_TRUE(mf.decodeMessage(rd, msg)); ASSERT_EQ(msg.getTID(), 1); @@ -55,8 +60,6 @@ TEST(MessageParser_Test, base_test_1) { MessageParser mp; mp.parse(rd.data(), rd.size()); - printf("SIZE: %lu\n", rd.size()); - ASSERT_EQ(mp.getMessageCount(), 1); shared_ptr p_msg = mp.getMessage();