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 0000000..91e2ceb Binary files /dev/null and b/src/communicate/.message_parser.cpp.swo differ diff --git a/src/communicate/message_factory.cpp b/src/communicate/message_factory.cpp index e80c9c5..b383a86 100644 --- a/src/communicate/message_factory.cpp +++ b/src/communicate/message_factory.cpp @@ -2,6 +2,7 @@ #include "communicate/message.h" #include +#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();