This commit is contained in:
Saturneric 2021-03-11 16:06:57 +08:00
parent abeb88b481
commit e9b667da26
5 changed files with 86 additions and 4 deletions

View File

@ -15,6 +15,7 @@ using std::queue;
namespace Net { namespace Net {
// the structure to store the option part of a message
class Option { class Option {
public: public:
Option(const string &key, const string &value); Option(const string &key, const string &value);
@ -34,6 +35,7 @@ public:
void updateValue(const string &value); void updateValue(const string &value);
private: private:
// the key is unique within a message
shared_ptr<string> key; shared_ptr<string> key;
shared_ptr<string> value; shared_ptr<string> value;
}; };
@ -105,30 +107,45 @@ private:
ssize_t decode_tail(const vector<char> &raw_Data, size_t offset, Message &msg); ssize_t decode_tail(const vector<char> &raw_Data, size_t offset, Message &msg);
void calculate_options_hash(const vector<char> &raw_data, int32_t end_index, int16_t &sum_hash);
SHA256Generator sign_gen; SHA256Generator sign_gen;
}; };
class MessageParser { class MessageParser {
public: public:
// send a received buffer to parse
void parse(const void *buf, size_t size); void parse(const void *buf, size_t size);
// Get a parsed message from the queue
shared_ptr<Message> getMessage(); shared_ptr<Message> getMessage();
// Get the count of the parsed meaasge
size_t getMessageCount(); size_t getMessageCount();
private: private:
// state recorder of a special part of a message
int head_state = -5; int head_state = -5;
int option_state = -4; int option_state = -4;
ssize_t body_state = -1; ssize_t body_state = -1;
int tail_state = -4; int tail_state = -4;
// factory used to read data and form the message step by step
MessageFactory factory; MessageFactory factory;
// store the message parsed
queue<shared_ptr<Message>> msgs; queue<shared_ptr<Message>> msgs;
// buffer to store the data give by
queue<char> buffer; queue<char> buffer;
// buffer to temporarily store the data of the certain part related to the state of the parser
vector<char> temp_buffer; vector<char> temp_buffer;
// temporarily record the message concentrated
shared_ptr<Message> temp_msg; shared_ptr<Message> temp_msg;
// reset all state and refresh the parser
void reset_state(); void reset_state();
void locate_head(); void locate_head();

Binary file not shown.

View File

@ -2,6 +2,7 @@
#include "communicate/message.h" #include "communicate/message.h"
#include <stdexcept> #include <stdexcept>
#include <stdio.h>
namespace Net { namespace Net {
@ -24,18 +25,21 @@ void MessageFactory::encode_head(const Message &msg, vector<char> &raw_data) {
raw_data.push_back(' '); raw_data.push_back(' ');
// 协议版本
const string s_version = std::to_string(msg.version); const string s_version = std::to_string(msg.version);
raw_data.insert(raw_data.end(), s_version.cbegin(), s_version.cend()); raw_data.insert(raw_data.end(), s_version.cbegin(), s_version.cend());
raw_data.push_back(' '); raw_data.push_back(' ');
// 消息类型
const string s_type = std::to_string(msg.type); const string s_type = std::to_string(msg.type);
raw_data.insert(raw_data.end(), s_type.cbegin(), s_type.cend()); raw_data.insert(raw_data.end(), s_type.cbegin(), s_type.cend());
raw_data.push_back(' '); raw_data.push_back(' ');
// 会话ID
const string s_tid = std::to_string(msg.tid); const string s_tid = std::to_string(msg.tid);
raw_data.insert(raw_data.end(), s_tid.cbegin(), s_tid.cend()); 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'); 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('\r');
raw_data.push_back('\n'); raw_data.push_back('\n');
} }
@ -158,8 +172,26 @@ ssize_t MessageFactory::decode_options(const vector<char> &raw_data,
msg.addOption(key.c_str(), value.c_str()); msg.addOption(key.c_str(), value.c_str());
} }
int sum_hash_range = index - 2;
--index; --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') if (raw_data[index++] != '\r' || raw_data[index++] != '\n')
return -1; return -1;
@ -200,6 +232,24 @@ ssize_t MessageFactory::decode_tail(const vector<char> &raw_data, size_t offset,
return index; return index;
} }
void MessageFactory::calculate_options_hash(const vector<char> &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<int16_t>(c);
sum_hash %= 65535;
if (index++ >= end_index) break;
}
}
bool MessageFactory::decodeMessage(const vector<char> &raw_data, Message &msg) { bool MessageFactory::decodeMessage(const vector<char> &raw_data, Message &msg) {
msg.clear(); msg.clear();
@ -251,4 +301,5 @@ bool MessageFactory::decodeMessageTail(const vector<char> &raw_data, Message &ms
if(!~decode_tail(raw_data, 0, msg)) return false; if(!~decode_tail(raw_data, 0, msg)) return false;
return true; return true;
} }
} // namespace Net } // namespace Net

View File

@ -6,12 +6,16 @@ namespace Net {
void MessageParser::parse(const void *buf, size_t size) { 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; const char *c_buf = (const char *)buf;
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
buffer.push(c_buf[i]); buffer.push(c_buf[i]);
} }
// process the data byte by byte until the queue is empty
while(!buffer.empty()) { while(!buffer.empty()) {
// if there is no message concentrated then create new message
if (temp_msg == nullptr) { if (temp_msg == nullptr) {
temp_msg = std::make_shared<Message>(); temp_msg = std::make_shared<Message>();
} }
@ -26,9 +30,12 @@ void MessageParser::parse(const void *buf, size_t size) {
locate_tail(); locate_tail();
} }
// tail processing done
if(!tail_state){ if(!tail_state){
// release the message concentrated
msgs.push(temp_msg); msgs.push(temp_msg);
temp_msg = nullptr; temp_msg = nullptr;
// reset the state of the parser
reset_state(); reset_state();
} }
} }
@ -91,6 +98,8 @@ void MessageParser::locate_option() {
option_state++; option_state++;
else if(c == '\r') else if(c == '\r')
option_state = -1; option_state = -1;
else if (c > 47 && c < 58)
option_state++;
continue; continue;
} }
if(option_state == -3) { if(option_state == -3) {
@ -219,8 +228,10 @@ void MessageParser::locate_tail() {
void MessageParser::reset_state() { void MessageParser::reset_state() {
temp_buffer.clear(); temp_buffer.clear();
// reset the message concentrated
if(temp_msg != nullptr) if(temp_msg != nullptr)
temp_msg->clear(); temp_msg->clear();
// reset the state recorder
head_state = -5; head_state = -5;
option_state = -4; option_state = -4;
body_state = -1; body_state = -1;

View File

@ -26,6 +26,11 @@ TEST(Message_Test, base_test_1) {
mf.encodeMessage(msg, rd); mf.encodeMessage(msg, rd);
PrintTools::printInfoBuffer(rd, "Message Raw Data"); PrintTools::printInfoBuffer(rd, "Message Raw Data");
for(auto &c : rd) {
printf("%c", c);
}
printf("\n");
ASSERT_TRUE(mf.decodeMessage(rd, msg)); ASSERT_TRUE(mf.decodeMessage(rd, msg));
ASSERT_EQ(msg.getTID(), 1); ASSERT_EQ(msg.getTID(), 1);
@ -55,8 +60,6 @@ TEST(MessageParser_Test, base_test_1) {
MessageParser mp; MessageParser mp;
mp.parse(rd.data(), rd.size()); mp.parse(rd.data(), rd.size());
printf("SIZE: %lu\n", rd.size());
ASSERT_EQ(mp.getMessageCount(), 1); ASSERT_EQ(mp.getMessageCount(), 1);
shared_ptr<Message> p_msg = mp.getMessage(); shared_ptr<Message> p_msg = mp.getMessage();