protocol: add basic communicate protocol pack and unpack.
This commit is contained in:
22
Protocol/CMakeLists.txt
Normal file
22
Protocol/CMakeLists.txt
Normal file
@@ -0,0 +1,22 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(Protocol LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core)
|
||||
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core)
|
||||
|
||||
set(SOURCES
|
||||
Protocol.cxx
|
||||
Protocol.h
|
||||
)
|
||||
|
||||
add_library(Protocol STATIC ${SOURCES})
|
||||
target_link_libraries(Protocol Qt${QT_VERSION_MAJOR}::Core)
|
||||
target_include_directories(Protocol PUBLIC ${CMAKE_CURRENT_LIST_DIR})
|
||||
97
Protocol/Protocol.cxx
Normal file
97
Protocol/Protocol.cxx
Normal file
@@ -0,0 +1,97 @@
|
||||
#include "Protocol.h"
|
||||
|
||||
#include <QIODevice>
|
||||
#include <cstdint>
|
||||
|
||||
Protocol::Protocol()
|
||||
{
|
||||
}
|
||||
|
||||
QSharedPointer<FrameBuffer> Protocol::ParseBuffer(QByteArray& buffer)
|
||||
{
|
||||
static QByteArray protocolHeader = QByteArray::fromRawData("\xFF\xFE", 2);
|
||||
static QByteArray protocolTail = QByteArray::fromRawData("\xFF\xFF", 2);
|
||||
|
||||
int headerPos = buffer.indexOf(protocolHeader);
|
||||
if (headerPos == -1) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const int minFrameSize = protocolHeader.size() + sizeof(uint16_t) + 32 + 32 + sizeof(uint32_t) + protocolTail.size();
|
||||
if (buffer.size() - headerPos < minFrameSize) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QDataStream stream(buffer.mid(headerPos));
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
|
||||
QByteArray header;
|
||||
header.resize(protocolHeader.size());
|
||||
stream.readRawData(header.data(), protocolHeader.size());
|
||||
if (header != protocolHeader) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
FrameBufferType type;
|
||||
stream >> reinterpret_cast<quint16&>(type);
|
||||
|
||||
QByteArray fidBytes(32, '\0');
|
||||
QByteArray tidBytes(32, '\0');
|
||||
stream.readRawData(fidBytes.data(), 32);
|
||||
stream.readRawData(tidBytes.data(), 32);
|
||||
|
||||
quint32 dataLen;
|
||||
stream >> dataLen;
|
||||
|
||||
int totalFrameSize = minFrameSize - protocolTail.size() + dataLen;
|
||||
if (buffer.size() - headerPos < totalFrameSize) {
|
||||
return nullptr;
|
||||
}
|
||||
QByteArray data;
|
||||
if (dataLen > 0) {
|
||||
data.resize(dataLen);
|
||||
stream.readRawData(data.data(), dataLen);
|
||||
}
|
||||
QByteArray tail;
|
||||
tail.resize(protocolTail.size());
|
||||
stream.readRawData(tail.data(), protocolTail.size());
|
||||
if (tail != protocolTail) {
|
||||
return nullptr;
|
||||
}
|
||||
auto frame = QSharedPointer<FrameBuffer>::create();
|
||||
frame->type = type;
|
||||
frame->fid = QString::fromUtf8(fidBytes).trimmed();
|
||||
frame->tid = QString::fromUtf8(tidBytes).trimmed();
|
||||
frame->data = data;
|
||||
buffer.remove(0, headerPos + totalFrameSize);
|
||||
return frame;
|
||||
}
|
||||
|
||||
QByteArray Protocol::PackBuffer(const QSharedPointer<FrameBuffer>& frame)
|
||||
{
|
||||
static QByteArray protocolHeader = QByteArray::fromRawData("\xFF\xFE", 2);
|
||||
static QByteArray protocolTail = QByteArray::fromRawData("\xFF\xFF", 2);
|
||||
|
||||
if (frame.isNull()) {
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
QByteArray packet;
|
||||
QDataStream stream(&packet, QIODevice::WriteOnly);
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
|
||||
stream.writeRawData(protocolHeader.constData(), protocolHeader.size());
|
||||
stream << static_cast<quint16>(frame->type);
|
||||
|
||||
QByteArray fidBytes = frame->fid.toUtf8().leftJustified(32, '\0', true);
|
||||
stream.writeRawData(fidBytes.constData(), 32);
|
||||
QByteArray tidBytes = frame->tid.toUtf8().leftJustified(32, '\0', true);
|
||||
stream.writeRawData(tidBytes.constData(), 32);
|
||||
|
||||
stream << static_cast<quint32>(frame->data.size());
|
||||
if (!frame->data.isEmpty()) {
|
||||
stream.writeRawData(frame->data.constData(), frame->data.size());
|
||||
}
|
||||
stream.writeRawData(protocolTail.constData(), protocolTail.size());
|
||||
return packet;
|
||||
}
|
||||
41
Protocol/Protocol.h
Normal file
41
Protocol/Protocol.h
Normal file
@@ -0,0 +1,41 @@
|
||||
#ifndef PROTOCOL_H
|
||||
#define PROTOCOL_H
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QSharedPointer>
|
||||
#include <QString>
|
||||
|
||||
// It is specified here that the first 30 contents (inclusive) are
|
||||
// used for communication with the server.
|
||||
// Contents beyond 30 are only forwarded.
|
||||
enum FrameBufferType : uint16_t {
|
||||
FBT_SER_MSG_ASKCLIENTS = 0,
|
||||
FBT_SER_MSG_YOURID,
|
||||
FBT_SER_MSG_RESPONSE,
|
||||
FBT_SER_MSG_FORWARD_FAILED,
|
||||
FBT_CLI_BIN_FILEDATA = 31,
|
||||
FBT_CLI_MSG_COMMUNICATE,
|
||||
FBT_CLI_ASK_DIRFILE,
|
||||
FBT_CLI_ANS_DIRFILE,
|
||||
FBT_CLI_ASK_HOME,
|
||||
FBT_CLI_ANS_HOME
|
||||
};
|
||||
|
||||
struct FrameBuffer {
|
||||
QByteArray data;
|
||||
QString fid;
|
||||
QString tid;
|
||||
FrameBufferType type;
|
||||
};
|
||||
|
||||
class Protocol
|
||||
{
|
||||
public:
|
||||
Protocol();
|
||||
|
||||
public:
|
||||
static QSharedPointer<FrameBuffer> ParseBuffer(QByteArray& buffer);
|
||||
static QByteArray PackBuffer(const QSharedPointer<FrameBuffer>& frame);
|
||||
};
|
||||
|
||||
#endif // PROTOCOL_H
|
||||
Reference in New Issue
Block a user