Message Added.
This commit is contained in:
parent
bccaca82fa
commit
abeb88b481
8
include/communicate/commu_options.h
Normal file
8
include/communicate/commu_options.h
Normal file
@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#define MSG_VERSION 0x0
|
||||
|
||||
namespace Net{
|
||||
|
||||
|
||||
}
|
144
include/communicate/message.h
Normal file
144
include/communicate/message.h
Normal file
@ -0,0 +1,144 @@
|
||||
#pragma once
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
#include <memory>
|
||||
|
||||
#include "communicate/commu_options.h"
|
||||
#include "utils/sha256_generator.h"
|
||||
|
||||
using std::string;
|
||||
using std::vector;
|
||||
using std::shared_ptr;
|
||||
using std::queue;
|
||||
|
||||
namespace Net {
|
||||
|
||||
class Option {
|
||||
public:
|
||||
Option(const string &key, const string &value);
|
||||
|
||||
Option(const Option &o);
|
||||
|
||||
Option(Option &&o) noexcept;
|
||||
|
||||
Option& operator=(const Option &o);
|
||||
|
||||
Option& operator=(Option &&o) noexcept;
|
||||
|
||||
const string &getKey() const;
|
||||
|
||||
const string &getValue() const;
|
||||
|
||||
void updateValue(const string &value);
|
||||
|
||||
private:
|
||||
shared_ptr<string> key;
|
||||
shared_ptr<string> value;
|
||||
};
|
||||
|
||||
class MessageFactory;
|
||||
|
||||
class Message {
|
||||
public:
|
||||
|
||||
Message() noexcept;
|
||||
|
||||
void setHead(int32_t tid, int16_t type);
|
||||
|
||||
void addOption(const string &key, const string &value);
|
||||
|
||||
const string &getValue(const string &key) const;
|
||||
|
||||
void pushData(void *const buf, size_t size);
|
||||
|
||||
int32_t getTID() const;
|
||||
|
||||
const vector<char> &getData() const;
|
||||
|
||||
void clear();
|
||||
|
||||
private:
|
||||
friend MessageFactory;
|
||||
|
||||
int32_t tid = -1;
|
||||
int16_t version = MSG_VERSION;
|
||||
int16_t type = 0x0;
|
||||
vector<Option> options = vector<Option>();
|
||||
vector<char> data = vector<char>();
|
||||
static const string msg_head;
|
||||
static const string msg_tail;
|
||||
|
||||
};
|
||||
|
||||
class MessageFactory {
|
||||
public:
|
||||
bool encodeMessage(Message &msg, vector<char> &raw_data);
|
||||
|
||||
bool decodeMessage(const vector<char> &raw_data, Message &msg);
|
||||
|
||||
bool decodeMessageHead(const vector<char> &raw_data, Message &msg);
|
||||
|
||||
bool decodeMessageOption(const vector<char> &raw_data, Message &msg);
|
||||
|
||||
bool decodeMessageBody(const vector<char> &raw_data, Message &msg);
|
||||
|
||||
bool decodeMessageTail(const vector<char> &raw_data, Message &msg);
|
||||
|
||||
bool checkMessageSign(const Message &msg);
|
||||
|
||||
private:
|
||||
void encode_head(const Message &msg, vector<char> &raw_data);
|
||||
|
||||
void encode_options(const Message &msg, vector<char> &raw_data);
|
||||
|
||||
void encode_body(const Message &msg, vector<char> &raw_data);
|
||||
|
||||
void encode_tail(const Message &msg, vector<char> &raw_data);
|
||||
|
||||
ssize_t decode_head(const vector<char> &raw_data, Message &msg);
|
||||
|
||||
ssize_t decode_options(const vector<char> &raw_data, size_t offset, Message &msg);
|
||||
|
||||
ssize_t decode_body(const vector<char> &raw_data, size_t offset, Message &msg);
|
||||
|
||||
ssize_t decode_tail(const vector<char> &raw_Data, size_t offset, Message &msg);
|
||||
|
||||
SHA256Generator sign_gen;
|
||||
};
|
||||
|
||||
class MessageParser {
|
||||
public:
|
||||
|
||||
void parse(const void *buf, size_t size);
|
||||
|
||||
shared_ptr<Message> getMessage();
|
||||
|
||||
size_t getMessageCount();
|
||||
|
||||
private:
|
||||
int head_state = -5;
|
||||
int option_state = -4;
|
||||
ssize_t body_state = -1;
|
||||
int tail_state = -4;
|
||||
MessageFactory factory;
|
||||
queue<shared_ptr<Message>> msgs;
|
||||
queue<char> buffer;
|
||||
vector<char> temp_buffer;
|
||||
|
||||
shared_ptr<Message> temp_msg;
|
||||
|
||||
void reset_state();
|
||||
|
||||
void locate_head();
|
||||
|
||||
void locate_option();
|
||||
|
||||
void locate_body();
|
||||
|
||||
void locate_tail();
|
||||
|
||||
};
|
||||
|
||||
} // namespace Net
|
@ -6,13 +6,39 @@
|
||||
#define NET_TCP_SERVER_H
|
||||
|
||||
// 基础依赖
|
||||
#include <boost/thread/pthread/mutex.hpp>
|
||||
#include <project.h>
|
||||
|
||||
// 扩展依赖
|
||||
#include "tcp.h"
|
||||
|
||||
using std::vector;
|
||||
|
||||
namespace Net {
|
||||
|
||||
class Message;
|
||||
|
||||
class Connection {
|
||||
public:
|
||||
Connection(int fd, struct sockaddr_in cli);
|
||||
|
||||
const std::string getIP() const;
|
||||
|
||||
const int16_t getPort() const;
|
||||
|
||||
void sendMessage(const Message &msg) {
|
||||
}
|
||||
|
||||
Message *recvMessage(uint32_t tid);
|
||||
|
||||
private:
|
||||
// socket fd
|
||||
int fd;
|
||||
|
||||
// Information structure of this connection
|
||||
struct sockaddr_in cli;
|
||||
};
|
||||
|
||||
//
|
||||
// Provide stable, reliable, easy-to-use, many-to-one TCP communication.
|
||||
// Requirement:
|
||||
|
@ -5,12 +5,15 @@
|
||||
#ifndef NET_PRINT_TOOLS_H
|
||||
#define NET_PRINT_TOOLS_H
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
using std::string;
|
||||
using std::initializer_list;
|
||||
using std::pair;
|
||||
using std::vector;
|
||||
|
||||
//提示信息打印类函数
|
||||
namespace Net {
|
||||
@ -19,16 +22,18 @@ namespace Net {
|
||||
|
||||
using FormalItem = pair<string, string>;
|
||||
|
||||
void debugPrintError(const string &error_info);
|
||||
void debugPrintError(const string error_info, ...);
|
||||
|
||||
void debugPrintWarning(const string &warning_info);
|
||||
void debugPrintWarning(const string warning_info, ...);
|
||||
|
||||
void debugPrintSuccess(const string &success_info);
|
||||
void debugPrintSuccess(const string success_info, ...);
|
||||
|
||||
void printInfo(const string& info, const string& tag);
|
||||
|
||||
void printInfoBuffer(const string& info, const string& tag);
|
||||
|
||||
void printInfoBuffer(const vector<char>& info, const string& tag);
|
||||
|
||||
void printInfoFormal(const string& title, initializer_list<FormalItem> body);
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@
|
||||
#include <sstream>
|
||||
|
||||
// 数据结构
|
||||
#include <vector>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <queue>
|
||||
|
||||
|
@ -2,12 +2,14 @@
|
||||
|
||||
#include <openssl/sha.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
#include <utility>
|
||||
|
||||
using std::string;
|
||||
using std::ifstream;
|
||||
using std::stringstream;
|
||||
using std::vector;
|
||||
|
||||
namespace Net {
|
||||
|
||||
@ -17,11 +19,11 @@ namespace Net {
|
||||
*/
|
||||
class SHA256Generator {
|
||||
public:
|
||||
SHA256Generator(string data);
|
||||
SHA256Generator();
|
||||
|
||||
SHA256Generator(ifstream stream);
|
||||
void setRawData(const string &str);
|
||||
|
||||
void replace(string &str);
|
||||
void setRawData(const vector<char> &c_array);
|
||||
|
||||
void generate();
|
||||
|
||||
@ -29,8 +31,9 @@ namespace Net {
|
||||
|
||||
private:
|
||||
bool if_generate = false;
|
||||
string raw_data;
|
||||
const void *raw_data = nullptr;
|
||||
size_t raw_data_size = 0;
|
||||
string sha256_data;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,3 @@
|
||||
file(GLOB commuSrc *.cpp)
|
||||
|
||||
add_library(commu STATIC ${commuSrc})
|
||||
add_library(commu STATIC ${commuSrc})
|
||||
|
70
src/communicate/message.cpp
Normal file
70
src/communicate/message.cpp
Normal file
@ -0,0 +1,70 @@
|
||||
#include "communicate/message.h"
|
||||
#include "communicate/commu_options.h"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
namespace Net {
|
||||
|
||||
const string Message::msg_head = "MSG";
|
||||
const string Message::msg_tail = "GSM";
|
||||
|
||||
void Message::addOption(const string &key, const string &value) {
|
||||
for (Option &option : options) {
|
||||
if (option.getKey() == key) {
|
||||
option.updateValue(value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
options.push_back(Option(key, value));
|
||||
}
|
||||
|
||||
const string &Message::getValue(const string &key) const {
|
||||
for (Option option : options) {
|
||||
if (option.getKey() == key) {
|
||||
return option.getValue();
|
||||
}
|
||||
}
|
||||
throw new std::runtime_error("key not found");
|
||||
}
|
||||
|
||||
void Message::pushData(void *const buf, size_t size) {
|
||||
char *const c_buf = (char *const)buf;
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
data.push_back(c_buf[i]);
|
||||
}
|
||||
|
||||
addOption("size", std::to_string(data.size()));
|
||||
|
||||
}
|
||||
|
||||
void Message::clear() {
|
||||
this->data.clear();
|
||||
this->options.clear();
|
||||
this->tid = 0;
|
||||
this->type = 0x1;
|
||||
}
|
||||
|
||||
void Message::setHead(int32_t tid, int16_t type) {
|
||||
this->tid = tid;
|
||||
this->type = type;
|
||||
}
|
||||
|
||||
int32_t Message::getTID() const {
|
||||
return tid;
|
||||
}
|
||||
|
||||
const vector<char> &Message::getData() const {
|
||||
return data;
|
||||
}
|
||||
|
||||
Message::Message() noexcept {
|
||||
|
||||
time_t t = time(nullptr);
|
||||
struct tm *p_tm = gmtime(&t);
|
||||
char buf[22];
|
||||
size_t w_bit = strftime(&buf[0], sizeof(buf), "%D %T %Z", p_tm);
|
||||
|
||||
addOption("date", buf);
|
||||
|
||||
}
|
||||
} // namespace Net
|
254
src/communicate/message_factory.cpp
Normal file
254
src/communicate/message_factory.cpp
Normal file
@ -0,0 +1,254 @@
|
||||
#include "communicate/commu_options.h"
|
||||
#include "communicate/message.h"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
namespace Net {
|
||||
|
||||
bool MessageFactory::encodeMessage(Message &msg, vector<char> &raw_data) {
|
||||
|
||||
sign_gen.setRawData(msg.getData());
|
||||
msg.addOption("sign", sign_gen.getHex());
|
||||
|
||||
encode_head(msg, raw_data);
|
||||
encode_options(msg, raw_data);
|
||||
encode_body(msg, raw_data);
|
||||
encode_tail(msg, raw_data);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MessageFactory::encode_head(const Message &msg, vector<char> &raw_data) {
|
||||
|
||||
raw_data.insert(raw_data.end(), msg.msg_head.cbegin(), msg.msg_head.cend());
|
||||
|
||||
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(' ');
|
||||
|
||||
const string s_tid = std::to_string(msg.tid);
|
||||
|
||||
raw_data.insert(raw_data.end(), s_tid.cbegin(), s_tid.cend());
|
||||
|
||||
raw_data.push_back('\r');
|
||||
raw_data.push_back('\n');
|
||||
}
|
||||
|
||||
void MessageFactory::encode_options(const Message &msg,
|
||||
vector<char> &raw_data) {
|
||||
|
||||
for (auto &option : msg.options) {
|
||||
raw_data.push_back('\"');
|
||||
|
||||
const string &key = option.getKey();
|
||||
|
||||
raw_data.insert(raw_data.end(), key.cbegin(), key.cend());
|
||||
|
||||
raw_data.push_back('\"');
|
||||
raw_data.push_back(':');
|
||||
raw_data.push_back('\"');
|
||||
|
||||
const string &value = option.getValue();
|
||||
|
||||
raw_data.insert(raw_data.end(), value.cbegin(), value.cend());
|
||||
|
||||
raw_data.push_back('\"');
|
||||
raw_data.push_back('\r');
|
||||
raw_data.push_back('\n');
|
||||
}
|
||||
|
||||
raw_data.push_back('\r');
|
||||
raw_data.push_back('\n');
|
||||
}
|
||||
|
||||
void MessageFactory::encode_body(const Message &msg, vector<char> &raw_data) {
|
||||
raw_data.insert(raw_data.end(), msg.data.begin(), msg.data.end());
|
||||
raw_data.push_back('\r');
|
||||
raw_data.push_back('\n');
|
||||
}
|
||||
|
||||
void MessageFactory::encode_tail(const Message &msg, vector<char> &raw_data) {
|
||||
raw_data.insert(raw_data.end(), msg.msg_tail.cbegin(), msg.msg_tail.cend());
|
||||
}
|
||||
|
||||
ssize_t MessageFactory::decode_head(const vector<char> &raw_data,
|
||||
Message &msg) {
|
||||
size_t index = 0;
|
||||
for (auto &c : Message::msg_head) {
|
||||
if (raw_data[index++] != c)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (raw_data[index++] != ' ')
|
||||
return -1;
|
||||
|
||||
string s_version;
|
||||
char c;
|
||||
while ((c = raw_data[index++]) != ' ') {
|
||||
s_version.push_back(c);
|
||||
}
|
||||
|
||||
int16_t version = std::stoi(s_version);
|
||||
|
||||
if (version != MSG_VERSION)
|
||||
return -1;
|
||||
|
||||
string s_type;
|
||||
while ((c = raw_data[index++]) != ' ') {
|
||||
s_type.push_back(c);
|
||||
}
|
||||
|
||||
int16_t type = std::stoi(s_type);
|
||||
|
||||
string s_tid;
|
||||
|
||||
while ((c = raw_data[index++]) != '\r') {
|
||||
s_tid.push_back(c);
|
||||
}
|
||||
|
||||
int32_t tid = std::stoi(s_tid);
|
||||
|
||||
if (raw_data[index++] != '\n')
|
||||
return -1;
|
||||
|
||||
msg.setHead(tid, type);
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
ssize_t MessageFactory::decode_options(const vector<char> &raw_data,
|
||||
size_t offset, Message &msg) {
|
||||
size_t index = offset;
|
||||
char c;
|
||||
while (raw_data[index++] == '\"') {
|
||||
|
||||
string key;
|
||||
|
||||
while ((c = raw_data[index++]) != '\"') {
|
||||
key.push_back(c);
|
||||
}
|
||||
|
||||
if (raw_data[index++] != ':') {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (raw_data[index++] != '\"') {
|
||||
return -1;
|
||||
}
|
||||
|
||||
string value;
|
||||
|
||||
while ((c = raw_data[index++]) != '\"') {
|
||||
value.push_back(c);
|
||||
}
|
||||
|
||||
if (raw_data[index++] != '\r' || raw_data[index++] != '\n')
|
||||
return -1;
|
||||
|
||||
msg.addOption(key.c_str(), value.c_str());
|
||||
}
|
||||
|
||||
--index;
|
||||
|
||||
if (raw_data[index++] != '\r' || raw_data[index++] != '\n')
|
||||
return -1;
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
ssize_t MessageFactory::decode_body(const vector<char> &raw_data, size_t offset,
|
||||
Message &msg) {
|
||||
size_t index = offset;
|
||||
int32_t size = 0;
|
||||
string s_size;
|
||||
try {
|
||||
s_size = msg.getValue("size");
|
||||
} catch (std::runtime_error e) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
size = std::stoi(s_size);
|
||||
|
||||
msg.pushData((void *)&raw_data[index], size);
|
||||
|
||||
index += size;
|
||||
|
||||
if (raw_data[index++] != '\r' || raw_data[index++] != '\n')
|
||||
return -1;
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
ssize_t MessageFactory::decode_tail(const vector<char> &raw_data, size_t offset,
|
||||
Message &msg) {
|
||||
size_t index = offset;
|
||||
for (auto &c : Message::msg_tail) {
|
||||
if (raw_data[index++] != c)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
bool MessageFactory::decodeMessage(const vector<char> &raw_data, Message &msg) {
|
||||
msg.clear();
|
||||
|
||||
ssize_t offset = decode_head(raw_data, msg);
|
||||
if (!~offset)
|
||||
return false;
|
||||
offset = decode_options(raw_data, offset, msg);
|
||||
if (!~offset)
|
||||
return false;
|
||||
offset = decode_body(raw_data, offset, msg);
|
||||
if (!~offset)
|
||||
return false;
|
||||
offset = decode_tail(raw_data, offset, msg);
|
||||
if (!~offset)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MessageFactory::checkMessageSign(const Message &msg) {
|
||||
string sign;
|
||||
|
||||
try {
|
||||
sign = msg.getValue("sign");
|
||||
} catch (std::runtime_error e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
sign_gen.setRawData(msg.getData());
|
||||
return sign_gen.getHex() == sign;
|
||||
}
|
||||
|
||||
bool MessageFactory::decodeMessageHead(const vector<char> &raw_data, Message &msg) {
|
||||
if(!~decode_head(raw_data, msg)) return false;
|
||||
else return true;
|
||||
}
|
||||
|
||||
bool MessageFactory::decodeMessageOption(const vector<char> &raw_data, Message &msg) {
|
||||
if(!~decode_options(raw_data, 0, msg)) return false;
|
||||
else return true;
|
||||
}
|
||||
|
||||
bool MessageFactory::decodeMessageBody(const vector<char> &raw_data, Message &msg) {
|
||||
if(!~decode_body(raw_data, 0, msg)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MessageFactory::decodeMessageTail(const vector<char> &raw_data, Message &msg) {
|
||||
if(!~decode_tail(raw_data, 0, msg)) return false;
|
||||
return true;
|
||||
}
|
||||
} // namespace Net
|
243
src/communicate/message_parser.cpp
Normal file
243
src/communicate/message_parser.cpp
Normal file
@ -0,0 +1,243 @@
|
||||
#include "communicate/message.h"
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
namespace Net {
|
||||
|
||||
void MessageParser::parse(const void *buf, size_t size) {
|
||||
|
||||
const char *c_buf = (const char *)buf;
|
||||
for (int i = 0; i < size; i++) {
|
||||
buffer.push(c_buf[i]);
|
||||
}
|
||||
|
||||
while(!buffer.empty()) {
|
||||
if (temp_msg == nullptr) {
|
||||
temp_msg = std::make_shared<Message>();
|
||||
}
|
||||
if (head_state < 0) {
|
||||
locate_head();
|
||||
} else if (option_state < 0) {
|
||||
locate_option();
|
||||
} else if (body_state != 0) {
|
||||
locate_body();
|
||||
}
|
||||
else if (tail_state < 0) {
|
||||
locate_tail();
|
||||
}
|
||||
|
||||
if(!tail_state){
|
||||
msgs.push(temp_msg);
|
||||
temp_msg = nullptr;
|
||||
reset_state();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MessageParser::locate_head() {
|
||||
|
||||
while (!buffer.empty()) {
|
||||
char c = buffer.front();
|
||||
buffer.pop();
|
||||
temp_buffer.push_back(c);
|
||||
if (head_state == -5) {
|
||||
if (c == 'M')
|
||||
head_state++;
|
||||
continue;
|
||||
}
|
||||
if (head_state == -4) {
|
||||
if (c != 'S') {
|
||||
reset_state();
|
||||
} else
|
||||
head_state++;
|
||||
continue;
|
||||
}
|
||||
if (head_state == -3) {
|
||||
if (c != 'G') {
|
||||
reset_state();
|
||||
} else
|
||||
head_state++;
|
||||
continue;
|
||||
}
|
||||
if (head_state == -2) {
|
||||
if (c == '\r') {
|
||||
head_state++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (head_state == -1) {
|
||||
if (c != '\n') {
|
||||
reset_state();
|
||||
} else {
|
||||
head_state++;
|
||||
if (!factory.decodeMessageHead(temp_buffer, *temp_msg)) {
|
||||
reset_state();
|
||||
}
|
||||
temp_buffer.clear();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MessageParser::locate_option() {
|
||||
while(!buffer.empty()) {
|
||||
char c = buffer.front();
|
||||
buffer.pop();
|
||||
temp_buffer.push_back(c);
|
||||
if(option_state == -4) {
|
||||
if(c == '\"')
|
||||
option_state++;
|
||||
else if(c == '\r')
|
||||
option_state = -1;
|
||||
continue;
|
||||
}
|
||||
if(option_state == -3) {
|
||||
if(c == '\r'){
|
||||
option_state++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(option_state == -2) {
|
||||
if(c == '\n'){
|
||||
option_state = -4;
|
||||
}
|
||||
else{
|
||||
reset_state();
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(option_state == -1) {
|
||||
if(c != '\n'){
|
||||
reset_state();
|
||||
break;
|
||||
}
|
||||
else{
|
||||
if(!factory.decodeMessageOption(temp_buffer, *temp_msg)) {
|
||||
reset_state();
|
||||
break;
|
||||
}
|
||||
option_state++;
|
||||
temp_buffer.clear();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MessageParser::locate_body() {
|
||||
while(!buffer.empty()) {
|
||||
char c = buffer.front();
|
||||
buffer.pop();
|
||||
temp_buffer.push_back(c);
|
||||
if(body_state == -1) {
|
||||
string s_size;
|
||||
try {
|
||||
s_size = temp_msg->getValue("size");
|
||||
} catch(std::runtime_error e) {
|
||||
reset_state();
|
||||
break;
|
||||
}
|
||||
body_state = std::stoul(s_size) + 2;
|
||||
}
|
||||
if(body_state > 1) {
|
||||
body_state--;
|
||||
continue;
|
||||
}
|
||||
if(body_state == 2) {
|
||||
if(c == '\r'){
|
||||
body_state--;
|
||||
continue;
|
||||
}
|
||||
else{
|
||||
reset_state();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(body_state == 1) {
|
||||
if(c != '\n'){
|
||||
reset_state();
|
||||
break;
|
||||
}
|
||||
else{
|
||||
if(!factory.decodeMessageBody(temp_buffer, *temp_msg)) {
|
||||
reset_state();
|
||||
break;
|
||||
}
|
||||
temp_buffer.clear();
|
||||
body_state--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MessageParser::locate_tail() {
|
||||
while(!buffer.empty()) {
|
||||
char c = buffer.front();
|
||||
buffer.pop();
|
||||
temp_buffer.push_back(c);
|
||||
if(tail_state == -4) {
|
||||
if(c == 'G')
|
||||
tail_state++;
|
||||
else{
|
||||
reset_state();
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(tail_state == -3) {
|
||||
if(c == 'S')
|
||||
tail_state++;
|
||||
else{
|
||||
reset_state();
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(tail_state == -2) {
|
||||
if(c == 'M')
|
||||
tail_state++;
|
||||
else{
|
||||
reset_state();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(tail_state == -1) {
|
||||
if(!factory.decodeMessageTail(temp_buffer, *temp_msg)) {
|
||||
reset_state();
|
||||
break;
|
||||
}
|
||||
tail_state++;
|
||||
temp_buffer.clear();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MessageParser::reset_state() {
|
||||
temp_buffer.clear();
|
||||
if(temp_msg != nullptr)
|
||||
temp_msg->clear();
|
||||
head_state = -5;
|
||||
option_state = -4;
|
||||
body_state = -1;
|
||||
tail_state = -4;
|
||||
}
|
||||
|
||||
shared_ptr<Message> MessageParser::getMessage() {
|
||||
shared_ptr<Message> p_msg = nullptr;
|
||||
if(!msgs.empty()){
|
||||
p_msg = msgs.front();
|
||||
msgs.pop();
|
||||
}
|
||||
return p_msg;
|
||||
}
|
||||
|
||||
size_t MessageParser::getMessageCount() {
|
||||
return msgs.size();
|
||||
}
|
||||
|
||||
} // namespace Net
|
40
src/communicate/option.cpp
Normal file
40
src/communicate/option.cpp
Normal file
@ -0,0 +1,40 @@
|
||||
#include "communicate/message.h"
|
||||
|
||||
namespace Net {
|
||||
|
||||
Option::Option(const string &key, const string &value)
|
||||
: key(std::make_shared<string>(key)), value(std::make_shared<string>(value)) {}
|
||||
|
||||
const string &Option::getKey() const { return *key; }
|
||||
|
||||
const string &Option::getValue() const { return *value; }
|
||||
|
||||
void Option::updateValue(const string &value) { *this->value = value; }
|
||||
|
||||
Option::Option(const Option &o) {
|
||||
if(this == &o) return;
|
||||
key = o.key;
|
||||
value = o.value;
|
||||
}
|
||||
|
||||
Option::Option(Option &&o) noexcept {
|
||||
if(this == &o) return;
|
||||
key = o.key;
|
||||
value = o.value;
|
||||
}
|
||||
|
||||
Option& Option::operator=(const Option &o) {
|
||||
if(this == &o) return *this;
|
||||
key = o.key;
|
||||
value = o.value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Option& Option::operator=(Option &&o) noexcept {
|
||||
if(this == &o) return *this;
|
||||
key = o.key;
|
||||
value = o.value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
} // namespace Net
|
@ -4,6 +4,8 @@
|
||||
|
||||
#include "communicate/tcp_server.h"
|
||||
#include "debug_tools/print_tools.h"
|
||||
#include <cstdio>
|
||||
#include <memory>
|
||||
|
||||
extern int errno;
|
||||
|
||||
@ -16,8 +18,13 @@ void Net::TCPServer::cycle() {
|
||||
void Net::TCPServer::connection_manager(Net::TCPServer *server) {
|
||||
Net::PrintTools::debugPrintSuccess("AcceptManager Started.");
|
||||
while (true) {
|
||||
int connect_fd = ::accept(server->fd, nullptr, nullptr);
|
||||
Net::PrintTools::debugPrintSuccess("New Connection.");
|
||||
struct sockaddr_in cli;
|
||||
socklen_t len = sizeof(cli);
|
||||
|
||||
int connect_fd = ::accept(server->fd, (struct sockaddr *)&cli, &len);
|
||||
Net::PrintTools::debugPrintSuccess("Get new connection from IP %s Port %d.",
|
||||
inet_ntoa(cli.sin_addr),
|
||||
htons(cli.sin_port));
|
||||
|
||||
if (connect_fd < 0)
|
||||
throw std::runtime_error(strerror(errno));
|
||||
@ -61,15 +68,14 @@ void Net::TCPServer::create_socket(int port) {
|
||||
this->server_addr.sin_port = htons(port);
|
||||
|
||||
// Try binding the socket to the given port
|
||||
if (bind(fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0){
|
||||
if (bind(fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
|
||||
// Close the socket created
|
||||
close(fd);
|
||||
throw std::runtime_error(strerror(errno));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Net::TCPServer::TCPServer(uint16_t port, uint32_t max_connection=1024) {
|
||||
Net::TCPServer::TCPServer(uint16_t port, uint32_t max_connection = 1024) {
|
||||
|
||||
// Create a new socket binding certain port
|
||||
create_socket(port);
|
||||
|
@ -7,48 +7,75 @@
|
||||
using std::string;
|
||||
|
||||
namespace Net {
|
||||
namespace PrintTools {
|
||||
void debugPrintError(const string &error_info) {
|
||||
printf("\033[31mError: %s\033[0m\n", error_info.data());
|
||||
}
|
||||
namespace PrintTools {
|
||||
|
||||
void debugPrintWarning(const string &warning_info) {
|
||||
printf("\033[33mWarning: %s\033[0m\n", warning_info.data());
|
||||
}
|
||||
void print_buff(uint8_t *const buf, size_t size);
|
||||
|
||||
void debugPrintSuccess(const string &success_info) {
|
||||
printf("\033[32m%s\033[0m\n", success_info.data());
|
||||
}
|
||||
void debugPrintError(const string error_info, ...) {
|
||||
va_list args;
|
||||
va_start(args, error_info);
|
||||
string output = "\033[31m[Error] ";
|
||||
output += error_info + string("\033[0m\n");
|
||||
vprintf(output.c_str(), args);
|
||||
}
|
||||
|
||||
void printInfo(const string& info, const string& tag) {
|
||||
printf("[DEBUG INFO] %s ", info.data());
|
||||
if(!tag.empty())
|
||||
printf("{ %s }\n",tag.data());
|
||||
}
|
||||
void debugPrintWarning(const string warning_info, ...) {
|
||||
va_list args;
|
||||
va_start(args, warning_info);
|
||||
string output = "\033[33m[Warning] ";
|
||||
output += warning_info + string("\033[0m\n");
|
||||
vprintf(output.c_str(), args);
|
||||
}
|
||||
|
||||
void printInfoFormal(const string& title, initializer_list<FormalItem> body) {
|
||||
printf("\n>>>\n {%s}\n",title.data());
|
||||
printf(">-------------------------------------\n");
|
||||
for(auto &item : body){
|
||||
printf("[%s] : \"%s\"; \n", item.first.data(), item.second.data());
|
||||
}
|
||||
printf("----------------------------------<\n<<<\n\n");
|
||||
}
|
||||
void debugPrintSuccess(const string success_info, ...) {
|
||||
va_list args;
|
||||
va_start(args, success_info);
|
||||
string output = "\033[32m[Success] ";
|
||||
output += success_info + string("\033[0m\n");
|
||||
vprintf(output.c_str(), args);
|
||||
}
|
||||
|
||||
void printInfoBuffer(const string &info, const string& tag) {
|
||||
printf("\n[DEBUG INFO (BUFFER)]\n");
|
||||
printf(">----------------------------------------------\n");
|
||||
auto *p_i = (uint8_t *) &info[0];
|
||||
auto *p_e = (uint8_t *) &info[info.size()-1];
|
||||
for(int c = 0;p_i < p_e; ++p_i, ++c){
|
||||
if(!(c % 16) && c) printf("\n");
|
||||
printf("%02x ",*p_i);
|
||||
void printInfo(const string &info, const string &tag) {
|
||||
printf("[DEBUG INFO] %s ", info.data());
|
||||
if (!tag.empty())
|
||||
printf("{ %s }\n", tag.data());
|
||||
}
|
||||
|
||||
}
|
||||
printf("\n");
|
||||
printf("----------------------------------------------<\n");
|
||||
if(!tag.empty())
|
||||
printf("{ %s }\n\n",tag.data());
|
||||
}
|
||||
}
|
||||
}
|
||||
void printInfoFormal(const string &title, initializer_list<FormalItem> body) {
|
||||
printf("\n>>>\n {%s}\n", title.data());
|
||||
printf(">-------------------------------------\n");
|
||||
for (auto &item : body) {
|
||||
printf("[%s] : \"%s\"; \n", item.first.data(), item.second.data());
|
||||
}
|
||||
printf("----------------------------------<\n<<<\n\n");
|
||||
}
|
||||
|
||||
void print_buff(uint8_t *const buf, size_t size) {
|
||||
|
||||
printf("\n[DEBUG INFO (BUFFER)]\n");
|
||||
printf(">----------------------------------------------\n");
|
||||
auto *p_i = buf;
|
||||
auto *p_e = (uint8_t *const) & buf[size - 1];
|
||||
for (int c = 0; p_i < p_e; ++p_i, ++c) {
|
||||
if (!(c % 16) && c)
|
||||
printf("\n");
|
||||
printf("%02x ", *p_i);
|
||||
}
|
||||
printf("\n");
|
||||
printf("----------------------------------------------<\n");
|
||||
}
|
||||
|
||||
void printInfoBuffer(const string &info, const string &tag) {
|
||||
print_buff((uint8_t *)&info[0], info.size());
|
||||
if (!tag.empty())
|
||||
printf("{ %s }\n\n", tag.data());
|
||||
}
|
||||
|
||||
void printInfoBuffer(const vector<char> &info, const string &tag) {
|
||||
print_buff((uint8_t *)&info[0], info.size());
|
||||
if (!tag.empty())
|
||||
printf("{ %s }\n\n", tag.data());
|
||||
}
|
||||
|
||||
} // namespace PrintTools
|
||||
} // namespace Net
|
||||
|
@ -8,10 +8,10 @@ void Net::SHA256Generator::generate() {
|
||||
unsigned char hash[SHA256_DIGEST_LENGTH];
|
||||
SHA256_CTX sha256;
|
||||
SHA256_Init(&sha256);
|
||||
SHA256_Update(&sha256, raw_data.c_str(), raw_data.size());
|
||||
SHA256_Update(&sha256, raw_data, raw_data_size);
|
||||
SHA256_Final(hash, &sha256);
|
||||
stringstream buffer;
|
||||
char buf[2];
|
||||
char buf[3];
|
||||
for(int i = 0; i < SHA256_DIGEST_LENGTH; ++i){
|
||||
sprintf(buf,"%02x",hash[i]);
|
||||
buffer << buf;
|
||||
@ -20,8 +20,16 @@ void Net::SHA256Generator::generate() {
|
||||
if_generate = true;
|
||||
}
|
||||
|
||||
void Net::SHA256Generator::replace(string &str) {
|
||||
this->raw_data = str;
|
||||
void Net::SHA256Generator::setRawData(const vector<char> &c_array) {
|
||||
raw_data = &c_array[0];
|
||||
raw_data_size = c_array.size();
|
||||
if_generate = false;
|
||||
}
|
||||
|
||||
void Net::SHA256Generator::setRawData(const string &str) {
|
||||
raw_data = str.c_str();
|
||||
raw_data_size = str.size();
|
||||
if_generate = false;
|
||||
}
|
||||
|
||||
string Net::SHA256Generator::getHex() {
|
||||
@ -29,13 +37,5 @@ string Net::SHA256Generator::getHex() {
|
||||
return this->sha256_data;
|
||||
}
|
||||
|
||||
Net::SHA256Generator::SHA256Generator(ifstream stream) {
|
||||
while (stream.good()) {
|
||||
stream >> raw_data;
|
||||
}
|
||||
stream.close();
|
||||
}
|
||||
|
||||
Net::SHA256Generator::SHA256Generator(string data) {
|
||||
this->raw_data = std::move(data);
|
||||
Net::SHA256Generator::SHA256Generator() {
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
find_package(GTest REQUIRED)
|
||||
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "-g")
|
||||
|
||||
set(GTEST_LIB /usr/local/lib/)
|
||||
set(GTEST_LIBS gtest gmock pthread dl)
|
||||
|
||||
@ -7,3 +9,4 @@ link_directories(${GTEST_LIB})
|
||||
|
||||
add_subdirectory(test_util)
|
||||
add_subdirectory(test_commu)
|
||||
add_subdirectory(test_commu_modules)
|
||||
|
@ -2,31 +2,21 @@
|
||||
// Created by 胡宇 on 2020/7/9.
|
||||
//
|
||||
|
||||
#include <unistd.h>
|
||||
#include <cstdio>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "debug_tools/print_tools.h"
|
||||
#include "communicate/tcp_server.h"
|
||||
#include "communicate/tcp_client.h"
|
||||
#include "communicate/tcp_server.h"
|
||||
#include "debug_tools/print_tools.h"
|
||||
|
||||
using namespace Net;
|
||||
|
||||
int main(int argc, char *argv[]){
|
||||
PrintTools::debugPrintSuccess("All Started.");
|
||||
if(fork() == 0) {
|
||||
PrintTools::debugPrintSuccess("Child Started.");
|
||||
TCPClient client("127.0.0.1", 9048);
|
||||
for(int i = 0; i < 32; i++, usleep(1e4))
|
||||
client.sendData("Hello\n");
|
||||
PrintTools::debugPrintSuccess("Child Exited.");
|
||||
}
|
||||
else{
|
||||
PrintTools::debugPrintSuccess("Father Started.");
|
||||
TCPServer server(9048, 100);
|
||||
while (true){
|
||||
std::putchar(server.readByte());
|
||||
usleep(1e3);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int main(int argc, char *argv[]) {
|
||||
PrintTools::debugPrintSuccess("TCPServer Started.");
|
||||
TCPServer server(9048, 100);
|
||||
while (true) {
|
||||
std::putchar(server.readByte());
|
||||
usleep(1e3);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
8
test/test_commu_modules/CMakeLists.txt
Normal file
8
test/test_commu_modules/CMakeLists.txt
Normal file
@ -0,0 +1,8 @@
|
||||
file(GLOB testSrc *.cpp)
|
||||
|
||||
add_executable(testCommuModules ${testSrc})
|
||||
|
||||
target_link_libraries(testCommuModules commu utils ssl crypto debugTools ${GTEST_LIBS})
|
||||
|
||||
add_test(Name testCommuModules
|
||||
COMMAND testCommuModules)
|
10
test/test_commu_modules/main.cpp
Normal file
10
test/test_commu_modules/main.cpp
Normal file
@ -0,0 +1,10 @@
|
||||
//
|
||||
// Created by Eric Saturn on 2019/12/12.
|
||||
//
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
int main(int argc, char *argv[]){
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
104
test/test_commu_modules/test_message.cpp
Normal file
104
test/test_commu_modules/test_message.cpp
Normal file
@ -0,0 +1,104 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "debug_tools/print_tools.h"
|
||||
#include "communicate/message.h"
|
||||
|
||||
using namespace Net;
|
||||
|
||||
TEST(Option_Test, base_test_1) {
|
||||
Option op = Option("Size", "123");
|
||||
Option op2 = std::move(op);
|
||||
|
||||
ASSERT_EQ(op.getKey(), "Size");
|
||||
ASSERT_EQ(op.getValue(), "123");
|
||||
|
||||
ASSERT_EQ(op2.getKey(), "Size");
|
||||
ASSERT_EQ(op2.getValue(), "123");
|
||||
}
|
||||
|
||||
TEST(Message_Test, base_test_1) {
|
||||
Message msg = Message();
|
||||
msg.setHead(1, 0x1);
|
||||
string buf = "hello world, wellcome";
|
||||
msg.pushData((void *const)buf.data(), buf.size());
|
||||
vector<char> rd;;
|
||||
MessageFactory mf;
|
||||
mf.encodeMessage(msg, rd);
|
||||
PrintTools::printInfoBuffer(rd, "Message Raw Data");
|
||||
|
||||
ASSERT_TRUE(mf.decodeMessage(rd, msg));
|
||||
|
||||
ASSERT_EQ(msg.getTID(), 1);
|
||||
|
||||
printf("SIGN: %s\n", msg.getValue("sign").c_str());;
|
||||
printf("DATE: %s\n", msg.getValue("date").c_str());;
|
||||
printf("SIZE: %s\n", msg.getValue("size").c_str());;
|
||||
|
||||
ASSERT_EQ(msg.getData()[20], 'e');
|
||||
ASSERT_EQ(msg.getData()[19], 'm');
|
||||
ASSERT_EQ(msg.getData()[0], 'h');
|
||||
|
||||
ASSERT_TRUE(mf.checkMessageSign(msg));
|
||||
|
||||
}
|
||||
|
||||
TEST(MessageParser_Test, base_test_1) {
|
||||
Message msg;
|
||||
msg.setHead(0x2, 0x1);
|
||||
msg.addOption("abc", "def");
|
||||
char buf[] = "Hello WWWWWWWW!";
|
||||
|
||||
msg.pushData(buf, sizeof(buf));
|
||||
MessageFactory mf;
|
||||
vector<char> rd;
|
||||
mf.encodeMessage(msg, rd);
|
||||
MessageParser mp;
|
||||
mp.parse(rd.data(), rd.size());
|
||||
|
||||
printf("SIZE: %lu\n", rd.size());
|
||||
|
||||
ASSERT_EQ(mp.getMessageCount(), 1);
|
||||
|
||||
shared_ptr<Message> p_msg = mp.getMessage();
|
||||
|
||||
ASSERT_EQ(p_msg->getData().size(), msg.getData().size());
|
||||
ASSERT_EQ(p_msg->getTID(), msg.getTID());
|
||||
ASSERT_EQ(p_msg->getValue("abc"), "def");
|
||||
|
||||
mp.parse(&rd[0], 8);
|
||||
mp.parse(&rd[8], 32);
|
||||
mp.parse(&rd[40], 100);
|
||||
mp.parse(&rd[140], 27);
|
||||
|
||||
ASSERT_EQ(mp.getMessageCount(), 1);
|
||||
|
||||
mp.parse(&rd[0], 14);
|
||||
mp.parse(&rd[14], 1);
|
||||
mp.parse(&rd[15], 34);
|
||||
mp.parse(&rd[49], 11);
|
||||
mp.parse(&rd[60], 107);
|
||||
|
||||
ASSERT_EQ(mp.getMessageCount(), 2);
|
||||
|
||||
p_msg = mp.getMessage();
|
||||
|
||||
ASSERT_EQ(p_msg->getData().size(), msg.getData().size());
|
||||
ASSERT_EQ(p_msg->getTID(), msg.getTID());
|
||||
ASSERT_EQ(p_msg->getValue("abc"), "def");
|
||||
|
||||
ASSERT_EQ(mp.getMessageCount(), 1);
|
||||
|
||||
mp.parse(&rd[0], 15);
|
||||
mp.parse(&rd[16], 34);
|
||||
mp.parse(&rd[50], 10);
|
||||
mp.parse(&rd[60], 107);
|
||||
|
||||
ASSERT_EQ(mp.getMessageCount(), 1);
|
||||
|
||||
mp.parse(&rd[0], 16);
|
||||
mp.parse(&rd[16], 34);
|
||||
mp.parse(&rd[50], 10);
|
||||
mp.parse(&rd[60], 107);
|
||||
|
||||
ASSERT_EQ(mp.getMessageCount(), 1);
|
||||
}
|
@ -10,11 +10,12 @@
|
||||
using namespace Net;
|
||||
|
||||
TEST(SHA256Test, base_test_1){
|
||||
SHA256Generator generator("Hello World.");
|
||||
SHA256Generator generator;
|
||||
generator.setRawData("Hello World.");
|
||||
generator.generate();
|
||||
|
||||
PrintTools::printInfo(generator.getHex(), "SHA256 Hex");
|
||||
|
||||
ASSERT_EQ(generator.getHex(),
|
||||
std::string("f4bb1975bf1f81f76ce824f7536c1e101a8060a632a52289d530a6f600d52c92"));
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user