protocol: add basic communicate protocol pack and unpack.

This commit is contained in:
2025-06-13 23:14:57 +08:00
parent 0ad2c34579
commit ff14e30d31
12 changed files with 1950 additions and 1 deletions

22
Protocol/CMakeLists.txt Normal file
View 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
View 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
View 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