From e8a27bb203fe2aff70390a5eca002d7438da9b0f Mon Sep 17 00:00:00 2001
From: mrDarker <mr.darker@163.com>
Date: 星期三, 22 十月 2025 14:24:34 +0800
Subject: [PATCH] Merge branch 'clh' into liuyang
---
SourceCode/Bond/DAQBridge/proto/ProtocolCodec.cpp | 663 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 663 insertions(+), 0 deletions(-)
diff --git a/SourceCode/Bond/DAQBridge/proto/ProtocolCodec.cpp b/SourceCode/Bond/DAQBridge/proto/ProtocolCodec.cpp
new file mode 100644
index 0000000..6a1d4a3
--- /dev/null
+++ b/SourceCode/Bond/DAQBridge/proto/ProtocolCodec.cpp
@@ -0,0 +1,663 @@
+#include "ProtocolCodec.h"
+#include <cstring> // std::memcpy
+#include <cstdio> // std::snprintf (如需日志)
+#include <vector>
+
+namespace Proto {
+
+ // ---------------------------
+ // Big-endian 基础编解码工具
+ // ---------------------------
+ void put_u16(std::vector<uint8_t>& v, uint16_t x) {
+ v.push_back(static_cast<uint8_t>((x >> 8) & 0xFF));
+ v.push_back(static_cast<uint8_t>(x & 0xFF));
+ }
+ void put_u32(std::vector<uint8_t>& v, uint32_t x) {
+ v.push_back(static_cast<uint8_t>((x >> 24) & 0xFF));
+ v.push_back(static_cast<uint8_t>((x >> 16) & 0xFF));
+ v.push_back(static_cast<uint8_t>((x >> 8) & 0xFF));
+ v.push_back(static_cast<uint8_t>(x & 0xFF));
+ }
+ void put_u64(std::vector<uint8_t>& v, uint64_t x) {
+ for (int i = 7; i >= 0; --i) v.push_back(static_cast<uint8_t>((x >> (i * 8)) & 0xFF));
+ }
+ uint16_t get_u16(const uint8_t* p) {
+ return static_cast<uint16_t>((uint16_t(p[0]) << 8) | uint16_t(p[1]));
+ }
+ uint32_t get_u32(const uint8_t* p) {
+ return (uint32_t(p[0]) << 24) | (uint32_t(p[1]) << 16) | (uint32_t(p[2]) << 8) | uint32_t(p[3]);
+ }
+ uint64_t get_u64(const uint8_t* p) {
+ uint64_t x = 0;
+ for (int i = 0; i < 8; ++i) { x = (x << 8) | p[i]; }
+ return x;
+ }
+ void put_f64_be(std::vector<uint8_t>& v, double d) {
+ static_assert(sizeof(double) == 8, "double must be 8 bytes");
+ uint64_t u;
+ std::memcpy(&u, &d, 8);
+ for (int i = 7; i >= 0; --i) v.push_back(static_cast<uint8_t>((u >> (i * 8)) & 0xFF));
+ }
+ double get_f64_be(const uint8_t* p) {
+ uint64_t u = 0;
+ for (int i = 0; i < 8; ++i) { u = (u << 8) | p[i]; }
+ double d;
+ std::memcpy(&d, &u, 8);
+ return d;
+ }
+
+ // 快速窥探正文 cmd(不做完整长度核对,保留你原本风格)
+ uint16_t peek_cmd(const std::vector<uint8_t>& f) {
+ if (f.size() < 12) return 0;
+ if (!(f[0] == kHead[0] && f[1] == kHead[1] && f[2] == kHead[2] && f[3] == kHead[3])) return 0;
+ return (uint16_t(f[10]) << 8) | f[11];
+ }
+
+ // 包装帧:4B头 + 4B dataId + 2B bodyLen + body + 1B尾
+ static inline void frame_wrap(uint32_t dataId, const std::vector<uint8_t>& body, std::vector<uint8_t>& out) {
+ out.clear();
+ out.reserve(4 + 4 + 2 + body.size() + 1);
+ out.push_back(kHead[0]); out.push_back(kHead[1]); out.push_back(kHead[2]); out.push_back(kHead[3]);
+ put_u32(out, dataId);
+ put_u16(out, static_cast<uint16_t>(body.size()));
+ out.insert(out.end(), body.begin(), body.end());
+ out.push_back(kTail);
+ }
+
+ // ---------------------------
+ // 0x0104 / 0xF104 Machines
+ // ---------------------------
+ std::vector<uint8_t> encodeRequestMachines(const ReqMachines& req) {
+ std::vector<uint8_t> body;
+ put_u16(body, CMD_REQ_MACHINES);
+
+ std::vector<uint8_t> out;
+ frame_wrap(req.dataId, body, out);
+ return out;
+ }
+
+ std::vector<uint8_t> encodeResponseMachines(const RspMachines& rsp) {
+ std::vector<uint8_t> body;
+ put_u16(body, CMD_RSP_MACHINES);
+ put_u16(body, static_cast<uint16_t>(rsp.machines.size()));
+ for (auto& m : rsp.machines) {
+ put_u32(body, m.id);
+ const uint16_t n = static_cast<uint16_t>(m.name.size());
+ put_u16(body, n);
+ body.insert(body.end(), m.name.begin(), m.name.end());
+ }
+
+ std::vector<uint8_t> out;
+ frame_wrap(rsp.dataId, body, out);
+ return out;
+ }
+
+ bool decodeRequestMachines(const std::vector<uint8_t>& f, ReqMachines& out) {
+ if (f.size() < 11) return false;
+ const uint8_t* p = f.data();
+ if (p[0] != kHead[0] || p[1] != kHead[1] || p[2] != kHead[2] || p[3] != kHead[3]) return false;
+ if (f.back() != kTail) return false;
+
+ out.dataId = get_u32(p + 4);
+ const uint16_t bodyLen = get_u16(p + 8);
+ if (10u + bodyLen + 1u != f.size()) return false;
+
+ const uint8_t* b = p + 10;
+ return (get_u16(b) == CMD_REQ_MACHINES);
+ }
+
+ bool decodeResponseMachines(const std::vector<uint8_t>& f, RspMachines& out) {
+ if (f.size() < 11) return false;
+ const uint8_t* p = f.data();
+ if (p[0] != kHead[0] || p[1] != kHead[1] || p[2] != kHead[2] || p[3] != kHead[3]) return false;
+ if (f.back() != kTail) return false;
+
+ out.dataId = get_u32(p + 4);
+ const uint16_t bodyLen = get_u16(p + 8);
+ if (10u + bodyLen + 1u != f.size()) return false;
+
+ const uint8_t* b = p + 10;
+ const uint8_t* e = b + bodyLen;
+
+ if (b + 2 + 2 > e) return false;
+ if (get_u16(b) != CMD_RSP_MACHINES) return false;
+ b += 2;
+ const uint16_t cnt = get_u16(b); b += 2;
+
+ out.machines.clear();
+ out.machines.reserve(cnt);
+ for (uint16_t i = 0; i < cnt; ++i) {
+ if (b + 4 + 2 > e) return false;
+ const uint32_t id = get_u32(b); b += 4;
+ const uint16_t n = get_u16(b); b += 2;
+ if (b + n > e) return false;
+ out.machines.push_back({ id, std::string(reinterpret_cast<const char*>(b), n) });
+ b += n;
+ }
+ return (b == e);
+ }
+
+ // ---------------------------
+ // 0x0001 / 0xF001 Version
+ // ---------------------------
+ std::vector<uint8_t> encodeRequestVersion(const ReqVersion& req) {
+ std::vector<uint8_t> body;
+ put_u16(body, CMD_REQ_VERSION);
+
+ std::vector<uint8_t> out;
+ frame_wrap(req.dataId, body, out);
+ return out;
+ }
+
+ std::vector<uint8_t> encodeResponseVersion(const RspVersion& rsp) {
+ std::vector<uint8_t> body;
+ put_u16(body, CMD_RSP_VERSION);
+ const uint16_t n = static_cast<uint16_t>(rsp.version.size());
+ put_u16(body, n);
+ body.insert(body.end(), rsp.version.begin(), rsp.version.end()); // UTF-8
+
+ std::vector<uint8_t> out;
+ frame_wrap(rsp.dataId, body, out);
+ return out;
+ }
+
+ bool decodeRequestVersion(const std::vector<uint8_t>& f, ReqVersion& out) {
+ if (f.size() < 11) return false;
+ const uint8_t* p = f.data();
+ if (p[0] != kHead[0] || p[1] != kHead[1] || p[2] != kHead[2] || p[3] != kHead[3]) return false;
+ if (f.back() != kTail) return false;
+
+ out.dataId = get_u32(p + 4);
+ const uint16_t bodyLen = get_u16(p + 8);
+ if (10u + bodyLen + 1u != f.size()) return false;
+ const uint8_t* b = p + 10;
+ return (get_u16(b) == CMD_REQ_VERSION);
+ }
+
+ bool decodeResponseVersion(const std::vector<uint8_t>& f, RspVersion& out) {
+ if (f.size() < 11) return false;
+ const uint8_t* p = f.data();
+ if (p[0] != kHead[0] || p[1] != kHead[1] || p[2] != kHead[2] || p[3] != kHead[3]) return false;
+ if (f.back() != kTail) return false;
+
+ out.dataId = get_u32(p + 4);
+ const uint16_t bodyLen = get_u16(p + 8);
+ if (10u + bodyLen + 1u != f.size()) return false;
+
+ const uint8_t* b = p + 10;
+ const uint8_t* e = b + bodyLen;
+
+ if (b + 2 + 2 > e) return false;
+ if (get_u16(b) != CMD_RSP_VERSION) return false;
+ b += 2;
+
+ const uint16_t n = get_u16(b); b += 2;
+ if (b + n > e) return false;
+ out.version.assign(reinterpret_cast<const char*>(b), n);
+ b += n;
+
+ return (b == e);
+ }
+
+ // ---------------------------
+ // 0x0103 / 0xF103 Stats
+ // ---------------------------
+ std::vector<uint8_t> encodeRequestStats(const ReqStats& req) {
+ std::vector<uint8_t> body;
+ put_u16(body, CMD_REQ_STATS);
+ put_u32(body, req.machineId);
+ put_u16(body, req.flags);
+
+ std::vector<uint8_t> out;
+ frame_wrap(req.dataId, body, out);
+ return out;
+ }
+
+ std::vector<uint8_t> encodeResponseStats(const RspStats& rsp) {
+ std::vector<uint8_t> body;
+ put_u16(body, CMD_RSP_STATS);
+ put_u32(body, rsp.machineId);
+ put_u16(body, static_cast<uint16_t>(rsp.channels.size()));
+
+ for (auto& c : rsp.channels) {
+ put_u32(body, c.channelId);
+ put_u64(body, c.earliestTs);
+ put_u64(body, c.latestTs);
+ put_u32(body, c.size);
+ const uint16_t n = static_cast<uint16_t>(c.name.size());
+ put_u16(body, n);
+ body.insert(body.end(), c.name.begin(), c.name.end());
+ }
+
+ std::vector<uint8_t> out;
+ frame_wrap(rsp.dataId, body, out);
+ return out;
+ }
+
+ bool decodeRequestStats(const std::vector<uint8_t>& f, ReqStats& out) {
+ if (f.size() < 11) return false;
+ const uint8_t* p = f.data();
+ if (p[0] != kHead[0] || p[1] != kHead[1] || p[2] != kHead[2] || p[3] != kHead[3]) return false;
+ if (f.back() != kTail) return false;
+
+ out.dataId = get_u32(p + 4);
+ const uint16_t bodyLen = get_u16(p + 8);
+ if (10u + bodyLen + 1u != f.size()) return false;
+
+ const uint8_t* b = p + 10;
+ const uint8_t* e = b + bodyLen;
+ if (b + 2 + 4 + 2 > e) return false;
+ if (get_u16(b) != CMD_REQ_STATS) return false;
+ b += 2;
+
+ out.machineId = get_u32(b); b += 4;
+ out.flags = get_u16(b); b += 2;
+
+ return (b == e);
+ }
+
+ bool decodeResponseStats(const std::vector<uint8_t>& f, RspStats& out) {
+ if (f.size() < 11) return false;
+ const uint8_t* p = f.data();
+ if (p[0] != kHead[0] || p[1] != kHead[1] || p[2] != kHead[2] || p[3] != kHead[3]) return false;
+ if (f.back() != kTail) return false;
+
+ out.dataId = get_u32(p + 4);
+ const uint16_t bodyLen = get_u16(p + 8);
+ if (10u + bodyLen + 1u != f.size()) return false;
+
+ const uint8_t* b = p + 10;
+ const uint8_t* e = b + bodyLen;
+
+ if (b + 2 + 4 + 2 > e) return false;
+ if (get_u16(b) != CMD_RSP_STATS) return false;
+ b += 2;
+
+ out.machineId = get_u32(b); b += 4;
+ const uint16_t cnt = get_u16(b); b += 2;
+
+ out.channels.clear();
+ out.channels.reserve(cnt);
+ for (uint16_t i = 0; i < cnt; ++i) {
+ if (b + 4 + 8 + 8 + 4 + 2 > e) return false;
+ ChannelStatInfo ci{};
+ ci.channelId = get_u32(b); b += 4;
+ ci.earliestTs = get_u64(b); b += 8;
+ ci.latestTs = get_u64(b); b += 8;
+ ci.size = get_u32(b); b += 4;
+
+ const uint16_t n = get_u16(b); b += 2;
+ if (b + n > e) return false;
+ ci.name.assign(reinterpret_cast<const char*>(b), n);
+ b += n;
+
+ out.channels.push_back(std::move(ci));
+ }
+ return (b == e);
+ }
+
+ // ---------------------------------------
+ // 0x0101 / 0xF101 Since(支持可选 batchId)
+ // ---------------------------------------
+ std::vector<uint8_t> encodeRequestSince(const ReqSince& req) {
+ std::vector<uint8_t> body;
+ put_u16(body, CMD_REQ_SINCE);
+ put_u32(body, req.machineId);
+ put_u32(body, req.channelId);
+ put_u64(body, req.sinceTsExclusive);
+ put_u16(body, req.maxCount);
+ put_u16(body, req.flags);
+ if (req.flags & SINCE_FLAG_HAS_BATCH) {
+ const uint16_t L = static_cast<uint16_t>(req.batchId.size());
+ put_u16(body, L);
+ body.insert(body.end(), req.batchId.begin(), req.batchId.end());
+ }
+
+ std::vector<uint8_t> out;
+ frame_wrap(req.dataId, body, out);
+ return out;
+ }
+
+ std::vector<uint8_t> encodeResponseSince(const RspSince& rsp) {
+ std::vector<uint8_t> body;
+ put_u16(body, CMD_RSP_SINCE);
+ put_u32(body, rsp.machineId);
+ put_u32(body, rsp.channelId);
+ put_u64(body, rsp.lastTsSent);
+ body.push_back(rsp.more ? 1u : 0u);
+ put_u16(body, static_cast<uint16_t>(rsp.samples.size()));
+ for (auto& s : rsp.samples) {
+ put_u64(body, s.ts_ms);
+ put_f64_be(body, s.value);
+ }
+
+ std::vector<uint8_t> out;
+ frame_wrap(rsp.dataId, body, out);
+ return out;
+ }
+
+ bool decodeRequestSince(const std::vector<uint8_t>& f, ReqSince& out) {
+ if (f.size() < 11) return false;
+ const uint8_t* p = f.data();
+ if (p[0] != kHead[0] || p[1] != kHead[1] || p[2] != kHead[2] || p[3] != kHead[3]) return false;
+ if (f.back() != kTail) return false;
+
+ out.dataId = get_u32(p + 4);
+ const uint16_t bodyLen = get_u16(p + 8);
+ if (10u + bodyLen + 1u != f.size()) return false;
+
+ const uint8_t* b = p + 10;
+ const uint8_t* e = b + bodyLen;
+
+ if (b + 2 > e) return false;
+ if (get_u16(b) != CMD_REQ_SINCE) return false;
+ b += 2;
+
+ if (b + 4 + 4 + 8 + 2 + 2 > e) return false;
+ out.machineId = get_u32(b); b += 4;
+ out.channelId = get_u32(b); b += 4;
+ out.sinceTsExclusive = get_u64(b); b += 8;
+ out.maxCount = get_u16(b); b += 2;
+ out.flags = get_u16(b); b += 2;
+
+ out.batchId.clear();
+ if (out.flags & SINCE_FLAG_HAS_BATCH) {
+ if (b + 2 > e) return false;
+ const uint16_t L = get_u16(b); b += 2;
+ if (b + L > e) return false;
+ out.batchId.assign(reinterpret_cast<const char*>(b), L);
+ b += L;
+ }
+
+ return (b == e);
+ }
+
+ bool decodeResponseSince(const std::vector<uint8_t>& f, RspSince& out) {
+ if (f.size() < 11) return false;
+ const uint8_t* p = f.data();
+ if (p[0] != kHead[0] || p[1] != kHead[1] || p[2] != kHead[2] || p[3] != kHead[3]) return false;
+ if (f.back() != kTail) return false;
+
+ out.dataId = get_u32(p + 4);
+ const uint16_t bodyLen = get_u16(p + 8);
+ if (10u + bodyLen + 1u != f.size()) return false;
+
+ const uint8_t* b = p + 10;
+ const uint8_t* e = b + bodyLen;
+
+ if (b + 2 > e) return false;
+ if (get_u16(b) != CMD_RSP_SINCE) return false;
+ b += 2;
+
+ if (b + 4 + 4 + 8 + 1 + 2 > e) return false;
+ out.machineId = get_u32(b); b += 4;
+ out.channelId = get_u32(b); b += 4;
+ out.lastTsSent = get_u64(b); b += 8;
+ out.more = *b++; // u8
+ const uint16_t cnt = get_u16(b); b += 2;
+
+ out.samples.clear();
+ out.samples.reserve(cnt);
+ for (uint16_t i = 0; i < cnt; ++i) {
+ if (b + 8 + 8 > e) return false;
+ const uint64_t ts = get_u64(b); b += 8;
+ const double v = get_f64_be(b); b += 8;
+ out.samples.push_back({ ts, v });
+ }
+ return (b == e);
+ }
+
+ // ---------------------------------------
+ // 0x0105 / 0xF105 SinceAll(整机多通道增量)
+ // ---------------------------------------
+ std::vector<uint8_t> encodeRequestSinceAll(const ReqSinceAll& req) {
+ std::vector<uint8_t> body;
+ put_u16(body, CMD_REQ_SINCE_ALL);
+ put_u32(body, req.machineId);
+ put_u64(body, req.sinceTsExclusive);
+ put_u16(body, req.maxPerChannel);
+ put_u16(body, req.flags);
+ if (req.flags & SINCE_FLAG_HAS_BATCH) {
+ const uint16_t L = static_cast<uint16_t>(req.batchId.size());
+ put_u16(body, L);
+ body.insert(body.end(), req.batchId.begin(), req.batchId.end());
+ }
+
+ std::vector<uint8_t> out;
+ frame_wrap(req.dataId, body, out);
+ return out;
+ }
+
+ std::vector<uint8_t> encodeResponseSinceAll(const RspSinceAll& rsp) {
+ std::vector<uint8_t> body;
+ put_u16(body, CMD_RSP_SINCE_ALL);
+ put_u32(body, rsp.machineId);
+ body.push_back(rsp.moreAny ? 1u : 0u);
+ put_u16(body, static_cast<uint16_t>(rsp.blocks.size()));
+
+ for (const auto& b : rsp.blocks) {
+ put_u32(body, b.channelId);
+ put_u64(body, b.lastTsSent);
+ body.push_back(b.more ? 1u : 0u);
+ put_u16(body, static_cast<uint16_t>(b.samples.size()));
+ for (const auto& sp : b.samples) {
+ put_u64(body, sp.ts_ms);
+ put_f64_be(body, sp.value);
+ }
+ }
+
+ std::vector<uint8_t> out;
+ frame_wrap(rsp.dataId, body, out);
+ return out;
+ }
+
+ bool decodeRequestSinceAll(const std::vector<uint8_t>& f, ReqSinceAll& out) {
+ if (f.size() < 11) return false;
+ const uint8_t* p = f.data();
+ if (p[0] != kHead[0] || p[1] != kHead[1] || p[2] != kHead[2] || p[3] != kHead[3]) return false;
+ if (f.back() != kTail) return false;
+
+ out.dataId = get_u32(p + 4);
+ const uint16_t bodyLen = get_u16(p + 8);
+ if (10u + bodyLen + 1u != f.size()) return false;
+
+ const uint8_t* b = p + 10;
+ const uint8_t* e = b + bodyLen;
+
+ if (b + 2 > e) return false;
+ if (get_u16(b) != CMD_REQ_SINCE_ALL) return false;
+ b += 2;
+
+ if (b + 4 + 8 + 2 + 2 > e) return false;
+ out.machineId = get_u32(b); b += 4;
+ out.sinceTsExclusive = get_u64(b); b += 8;
+ out.maxPerChannel = get_u16(b); b += 2;
+ out.flags = get_u16(b); b += 2;
+
+ out.batchId.clear();
+ if (out.flags & SINCE_FLAG_HAS_BATCH) {
+ if (b + 2 > e) return false;
+ const uint16_t L = get_u16(b); b += 2;
+ if (b + L > e) return false;
+ out.batchId.assign(reinterpret_cast<const char*>(b), L);
+ b += L;
+ }
+ return (b == e);
+ }
+
+ bool decodeResponseSinceAll(const std::vector<uint8_t>& f, RspSinceAll& out) {
+ if (f.size() < 11) return false;
+ const uint8_t* p = f.data();
+ if (p[0] != kHead[0] || p[1] != kHead[1] || p[2] != kHead[2] || p[3] != kHead[3]) return false;
+ if (f.back() != kTail) return false;
+
+ out.dataId = get_u32(p + 4);
+ const uint16_t bodyLen = get_u16(p + 8);
+ if (10u + bodyLen + 1u != f.size()) return false;
+
+ const uint8_t* b = p + 10;
+ const uint8_t* e = b + bodyLen;
+
+ if (b + 2 > e) return false;
+ if (get_u16(b) != CMD_RSP_SINCE_ALL) return false;
+ b += 2;
+
+ if (b + 4 + 1 + 2 > e) return false;
+ out.machineId = get_u32(b); b += 4;
+ out.moreAny = *b++; // u8
+ const uint16_t N = get_u16(b); b += 2;
+
+ out.blocks.clear();
+ out.blocks.reserve(N);
+ for (uint16_t i = 0; i < N; ++i) {
+ if (b + 4 + 8 + 1 + 2 > e) return false;
+ ChannelBlock blk;
+ blk.channelId = get_u32(b); b += 4;
+ blk.lastTsSent = get_u64(b); b += 8;
+ blk.more = *b++; // u8
+ const uint16_t M = get_u16(b); b += 2;
+
+ blk.samples.clear();
+ blk.samples.reserve(M);
+ for (uint16_t j = 0; j < M; ++j) {
+ if (b + 8 + 8 > e) return false;
+ SamplePair sp;
+ sp.ts_ms = get_u64(b); b += 8;
+ sp.value = get_f64_be(b); b += 8;
+ blk.samples.push_back(sp);
+ }
+ out.blocks.push_back(std::move(blk));
+ }
+ return (b == e);
+ }
+
+ // ---------------------------
+ // 0x0120 / 0xF120 BatchInfo
+ // ---------------------------
+ std::vector<uint8_t> encodeRequestBatchInfo(const ReqBatchInfo& req) {
+ std::vector<uint8_t> body;
+ put_u16(body, CMD_REQ_BATCH_INFO);
+ put_u32(body, req.machineId);
+
+ std::vector<uint8_t> out;
+ frame_wrap(req.dataId, body, out);
+ return out;
+ }
+
+ bool decodeRequestBatchInfo(const std::vector<uint8_t>& f, ReqBatchInfo& out) {
+ if (f.size() < 11) return false;
+ const uint8_t* p = f.data();
+ if (p[0] != kHead[0] || p[1] != kHead[1] || p[2] != kHead[2] || p[3] != kHead[3]) return false;
+ if (f.back() != kTail) return false;
+
+ out.dataId = get_u32(p + 4);
+ const uint16_t bodyLen = get_u16(p + 8);
+ if (10u + bodyLen + 1u != f.size()) return false;
+
+ const uint8_t* b = p + 10;
+ const uint8_t* e = b + bodyLen;
+
+ if (b + 2 + 4 > e) return false;
+ if (get_u16(b) != CMD_REQ_BATCH_INFO) return false;
+ b += 2;
+
+ out.machineId = get_u32(b); b += 4;
+ return (b == e);
+ }
+
+ std::vector<uint8_t> encodeResponseBatchInfo(const RspBatchInfo& rsp) {
+ std::vector<uint8_t> body;
+ put_u16(body, CMD_RSP_BATCH_INFO);
+ put_u32(body, rsp.machineId);
+ body.push_back(static_cast<uint8_t>(rsp.state));
+
+ const uint16_t L = static_cast<uint16_t>(rsp.activeBatchId.size());
+ put_u16(body, L);
+ body.insert(body.end(), rsp.activeBatchId.begin(), rsp.activeBatchId.end());
+
+ put_u64(body, rsp.activeStartTs);
+ put_u64(body, rsp.expectedEndTs);
+
+ std::vector<uint8_t> out;
+ frame_wrap(rsp.dataId, body, out);
+ return out;
+ }
+
+ bool decodeResponseBatchInfo(const std::vector<uint8_t>& f, RspBatchInfo& out) {
+ if (f.size() < 11) return false;
+ const uint8_t* p = f.data();
+ if (p[0] != kHead[0] || p[1] != kHead[1] || p[2] != kHead[2] || p[3] != kHead[3]) return false;
+ if (f.back() != kTail) return false;
+
+ out.dataId = get_u32(p + 4);
+ const uint16_t bodyLen = get_u16(p + 8);
+ if (10u + bodyLen + 1u != f.size()) return false;
+
+ const uint8_t* b = p + 10;
+ const uint8_t* e = b + bodyLen;
+
+ if (b + 2 + 4 + 1 + 2 > e) return false;
+ if (get_u16(b) != CMD_RSP_BATCH_INFO) return false;
+ b += 2;
+
+ out.machineId = get_u32(b); b += 4;
+ out.state = static_cast<BatchState>(*b++);
+
+ const uint16_t L = get_u16(b); b += 2;
+ if (b + L > e) return false;
+ out.activeBatchId.assign(reinterpret_cast<const char*>(b), L); b += L;
+
+ if (b + 8 + 8 > e) return false;
+ out.activeStartTs = get_u64(b); b += 8;
+ out.expectedEndTs = get_u64(b); b += 8;
+
+ return (b == e);
+ }
+
+ // ---------------------------
+ // 0xE100 Error
+ // ---------------------------
+ std::vector<uint8_t> encodeResponseError(const RspError& rsp) {
+ std::vector<uint8_t> body;
+ put_u16(body, CMD_RSP_ERROR);
+ put_u16(body, rsp.refCmd);
+ put_u32(body, rsp.machineId);
+ put_u16(body, static_cast<uint16_t>(rsp.code));
+ const uint16_t L = static_cast<uint16_t>(rsp.message.size());
+ put_u16(body, L);
+ body.insert(body.end(), rsp.message.begin(), rsp.message.end());
+
+ std::vector<uint8_t> out;
+ frame_wrap(rsp.dataId, body, out);
+ return out;
+ }
+
+ bool decodeResponseError(const std::vector<uint8_t>& f, RspError& out) {
+ if (f.size() < 11) return false;
+ const uint8_t* p = f.data();
+ if (p[0] != kHead[0] || p[1] != kHead[1] || p[2] != kHead[2] || p[3] != kHead[3]) return false;
+ if (f.back() != kTail) return false;
+
+ out.dataId = get_u32(p + 4);
+ const uint16_t bodyLen = get_u16(p + 8);
+ if (10u + bodyLen + 1u != f.size()) return false;
+
+ const uint8_t* b = p + 10;
+ const uint8_t* e = b + bodyLen;
+
+ if (b + 2 + 2 + 4 + 2 + 2 > e) return false;
+ if (get_u16(b) != CMD_RSP_ERROR) return false;
+ b += 2;
+
+ out.refCmd = get_u16(b); b += 2;
+ out.machineId = get_u32(b); b += 4;
+ out.code = static_cast<ErrCode>(get_u16(b)); b += 2;
+
+ const uint16_t L = get_u16(b); b += 2;
+ if (b + L > e) return false;
+ out.message.assign(reinterpret_cast<const char*>(b), L); b += L;
+
+ return (b == e);
+ }
+
+} // namespace Proto
--
Gitblit v1.9.3