141 lines
5.0 KiB
C++
141 lines
5.0 KiB
C++
#include "message_bus/ingress/EdgeUplinkWire.h"
|
|
|
|
#include <cstring>
|
|
|
|
#include <QtEndian>
|
|
|
|
#include "utils/logs/logging.h"
|
|
|
|
namespace softbus::message_bus::ingress::edge_uplink
|
|
{
|
|
|
|
static std::uint16_t readU16BE(const unsigned char* p)
|
|
{
|
|
return qFromBigEndian<quint16>(reinterpret_cast<const quint8*>(p));
|
|
}
|
|
|
|
static std::uint32_t readU32BE(const unsigned char* p)
|
|
{
|
|
return qFromBigEndian<quint32>(reinterpret_cast<const quint8*>(p));
|
|
}
|
|
|
|
static std::int32_t readI32BE(const unsigned char* p)
|
|
{
|
|
return static_cast<std::int32_t>(readU32BE(p));
|
|
}
|
|
|
|
static std::int64_t readI64BE(const unsigned char* p)
|
|
{
|
|
return qFromBigEndian<qint64>(reinterpret_cast<const quint8*>(p));
|
|
}
|
|
|
|
static std::uint64_t readU64BE(const unsigned char* p)
|
|
{
|
|
return qFromBigEndian<quint64>(reinterpret_cast<const quint8*>(p));
|
|
}
|
|
|
|
QByteArray encodeOuterFrame(FrameKind kind, const QByteArray& payload)
|
|
{
|
|
QByteArray out;
|
|
out.resize(static_cast<int>(kOuterHeaderBytes + payload.size()));
|
|
unsigned char* d = reinterpret_cast<unsigned char*>(out.data());
|
|
d[0] = static_cast<unsigned char>(kMagic0);
|
|
d[1] = static_cast<unsigned char>(kMagic1);
|
|
d[2] = static_cast<unsigned char>(kMagic2);
|
|
d[3] = static_cast<unsigned char>(kMagic3);
|
|
qToBigEndian(kWireVersion, d + 4);
|
|
qToBigEndian(static_cast<std::uint16_t>(kind), d + 6);
|
|
qToBigEndian(static_cast<std::uint32_t>(0), d + 8);
|
|
qToBigEndian(static_cast<std::uint32_t>(payload.size()), d + 12);
|
|
if (!payload.isEmpty()) {
|
|
std::memcpy(d + kOuterHeaderBytes, payload.constData(), static_cast<std::size_t>(payload.size()));
|
|
}
|
|
return out;
|
|
}
|
|
|
|
std::optional<OuterFramePop> tryPopOneOuterFrame(QByteArray& buffer, int maxPayloadBytes)
|
|
{
|
|
if (buffer.size() < static_cast<int>(kOuterHeaderBytes)) {
|
|
return std::nullopt;
|
|
}
|
|
const unsigned char* d = reinterpret_cast<const unsigned char*>(buffer.constData());
|
|
if (d[0] != static_cast<unsigned char>(kMagic0) || d[1] != static_cast<unsigned char>(kMagic1)
|
|
|| d[2] != static_cast<unsigned char>(kMagic2) || d[3] != static_cast<unsigned char>(kMagic3)) {
|
|
LOG_WARNING() << "EdgeUplinkWire: bad magic, dropping byte";
|
|
buffer.remove(0, 1);
|
|
return std::nullopt;
|
|
}
|
|
const std::uint16_t ver = readU16BE(d + 4);
|
|
if (ver != kWireVersion) {
|
|
LOG_WARNING() << "EdgeUplinkWire: unsupported wire_version" << ver;
|
|
buffer.clear();
|
|
return std::nullopt;
|
|
}
|
|
const std::uint32_t payloadLen = readU32BE(d + 12);
|
|
if (maxPayloadBytes > 0 && payloadLen > static_cast<std::uint32_t>(maxPayloadBytes)) {
|
|
LOG_WARNING() << "EdgeUplinkWire: payload_len exceeds max" << payloadLen << maxPayloadBytes;
|
|
buffer.clear();
|
|
return std::nullopt;
|
|
}
|
|
const int total = static_cast<int>(kOuterHeaderBytes) + static_cast<int>(payloadLen);
|
|
if (payloadLen > 64u * 1024u * 1024u) {
|
|
LOG_WARNING() << "EdgeUplinkWire: absurd payload_len" << payloadLen;
|
|
buffer.clear();
|
|
return std::nullopt;
|
|
}
|
|
if (buffer.size() < total) {
|
|
return std::nullopt;
|
|
}
|
|
OuterFramePop fr;
|
|
fr.kind = static_cast<FrameKind>(readU16BE(d + 6));
|
|
fr.payload = QByteArray(buffer.constData() + static_cast<int>(kOuterHeaderBytes), static_cast<int>(payloadLen));
|
|
fr.consumedBytes = total;
|
|
buffer.remove(0, total);
|
|
return fr;
|
|
}
|
|
|
|
bool decodeDataRawBusPayload(const QByteArray& payload,
|
|
softbus::core::models::RawBusMessage& ctx,
|
|
QByteArray& busPayloadOut,
|
|
QString* errorMessage)
|
|
{
|
|
if (payload.size() < static_cast<int>(kDataRawBusFixedBytes)) {
|
|
if (errorMessage) {
|
|
*errorMessage = QStringLiteral("data_rawbus_too_short");
|
|
}
|
|
return false;
|
|
}
|
|
const unsigned char* p = reinterpret_cast<const unsigned char*>(payload.constData());
|
|
const std::uint16_t traceLen = readU16BE(p + 0);
|
|
if (traceLen > static_cast<std::uint16_t>(kMaxTraceLen)) {
|
|
if (errorMessage) {
|
|
*errorMessage = QStringLiteral("trace_too_long");
|
|
}
|
|
return false;
|
|
}
|
|
const int need = static_cast<int>(kDataRawBusFixedBytes) + static_cast<int>(traceLen);
|
|
if (payload.size() < need) {
|
|
if (errorMessage) {
|
|
*errorMessage = QStringLiteral("data_rawbus_truncated_trace");
|
|
}
|
|
return false;
|
|
}
|
|
ctx = {};
|
|
ctx.deviceId = readI32BE(p + 2);
|
|
ctx.endpointHash = readU32BE(p + 6);
|
|
ctx.protocol = static_cast<softbus::core::models::ProtocolType>(readU16BE(p + 10));
|
|
ctx.logicalAddress = readU32BE(p + 14);
|
|
ctx.routingKey = readU64BE(p + 18);
|
|
std::memcpy(&ctx.header, p + 26, 8);
|
|
ctx.timestampMs = readI64BE(p + 34);
|
|
ctx.direction = static_cast<softbus::core::models::BusDirection>(static_cast<signed char>(p[42]));
|
|
if (traceLen > 0) {
|
|
ctx.traceId = QString::fromUtf8(reinterpret_cast<const char*>(p + 48), static_cast<int>(traceLen));
|
|
}
|
|
busPayloadOut = payload.mid(need);
|
|
ctx.payload = {};
|
|
return true;
|
|
}
|
|
|
|
} // namespace softbus::message_bus::ingress::edge_uplink
|