Add buffer

This commit is contained in:
2025-12-25 13:39:39 +00:00
parent 86947912dc
commit a818813877
7 changed files with 178 additions and 94 deletions
+5
View File
@@ -7,6 +7,11 @@ add_library(Metrics
add_library(Metrics::All ALIAS Metrics)
target_link_libraries(Metrics
PRIVATE
Network::Common
)
target_include_directories(Metrics
PUBLIC
${INCLUDE_BASE_DIR}
+38 -93
View File
@@ -4,6 +4,8 @@
#include <cstring>
#include <arpa/inet.h>
#include "Network/Common/Buffer.h"
namespace Metrics
{
@@ -27,126 +29,69 @@ namespace Metrics
// ---- Сериализация ----
std::vector<uint8_t> Host::serialize() const
{
std::vector<uint8_t> buffer;
buffer.push_back(1); // версия протокола
Network::Buffer buf;
// Host
buffer.push_back(static_cast<uint8_t>(hostname.size()));
buffer.insert(buffer.end(), hostname.begin(), hostname.end());
buf.writeUint8(1); // version
buf.writeString(hostname);
// CPU
uint32_t totalLoadNet = floatToNetwork(cpu.totalLoad);
buffer.insert(buffer.end(),
reinterpret_cast<uint8_t *>(&totalLoadNet),
reinterpret_cast<uint8_t *>(&totalLoadNet) + sizeof(totalLoadNet));
buffer.push_back(static_cast<uint8_t>(cpu.coreLoads.size()));
buf.writeFloat(cpu.totalLoad);
buf.writeUint8(static_cast<uint8_t>(cpu.coreLoads.size()));
for (float f : cpu.coreLoads)
{
uint32_t net = floatToNetwork(f);
buffer.insert(buffer.end(),
reinterpret_cast<uint8_t *>(&net),
reinterpret_cast<uint8_t *>(&net) + 4);
}
buf.writeFloat(f);
// Memory
uint32_t usedNet = floatToNetwork(memory.used);
uint32_t totalNet = floatToNetwork(memory.total);
buffer.insert(buffer.end(),
reinterpret_cast<uint8_t *>(&usedNet),
reinterpret_cast<uint8_t *>(&usedNet) + sizeof(usedNet));
buffer.insert(buffer.end(),
reinterpret_cast<uint8_t *>(&totalNet),
reinterpret_cast<uint8_t *>(&totalNet) + sizeof(totalNet));
buf.writeFloat(memory.used);
buf.writeFloat(memory.total);
// Disks
buffer.push_back(static_cast<uint8_t>(disks.size()));
buf.writeUint8(static_cast<uint8_t>(disks.size()));
for (const auto &d : disks)
{
buffer.push_back(static_cast<uint8_t>(d.name.size()));
buffer.insert(buffer.end(), d.name.begin(), d.name.end());
uint32_t used = floatToNetwork(d.used);
uint32_t total = floatToNetwork(d.total);
buffer.insert(buffer.end(),
reinterpret_cast<uint8_t *>(&used),
reinterpret_cast<uint8_t *>(&used) + 4);
buffer.insert(buffer.end(),
reinterpret_cast<uint8_t *>(&total),
reinterpret_cast<uint8_t *>(&total) + 4);
buf.writeString(d.name);
buf.writeFloat(d.used);
buf.writeFloat(d.total);
}
return buffer;
return buf.data();
}
// ---- Десериализация ----
Host Host::deserialize(const std::vector<uint8_t> &buffer)
Host Host::deserialize(const std::vector<uint8_t> &data)
{
Host m;
size_t pos = 0;
if (buffer.size() < 1)
throw std::runtime_error("Buffer too small");
uint8_t version = buffer[pos++];
Host h;
Network::Buffer buf(const_cast<std::vector<uint8_t> &>(data));
uint8_t version = buf.readUint8();
if (version != 1)
throw std::runtime_error("Unsupported protocol version");
// Host
uint8_t hostLen = buffer[pos++];
if (pos + hostLen > buffer.size())
throw std::runtime_error("Buffer too small for host");
m.hostname = std::string(buffer.begin() + pos, buffer.begin() + pos + hostLen);
pos += hostLen;
h.hostname = buf.readString();
// CPU
uint32_t totolLoad;
std::memcpy(&totolLoad, &buffer[pos], 4);
pos += 4;
m.cpu.totalLoad = networkToFloat(totolLoad);
uint8_t numCpu = buffer[pos++];
if (pos + numCpu * 4 > buffer.size())
throw std::runtime_error("Buffer too small for CPU");
for (int i = 0; i < numCpu; ++i)
{
uint32_t tmp;
std::memcpy(&tmp, &buffer[pos], 4);
m.cpu.coreLoads.push_back(networkToFloat(tmp));
pos += 4;
}
h.cpu.totalLoad = buf.readFloat();
uint8_t numCpu = buf.readUint8();
h.cpu.coreLoads.clear();
h.cpu.coreLoads.reserve(numCpu);
for (uint8_t i = 0; i < numCpu; ++i)
h.cpu.coreLoads.push_back(buf.readFloat());
// Memory
if (pos + 8 > buffer.size())
throw std::runtime_error("Buffer too small for memory");
uint32_t memUsed, memTotal;
std::memcpy(&memUsed, &buffer[pos], 4);
pos += 4;
std::memcpy(&memTotal, &buffer[pos], 4);
pos += 4;
m.memory.used = networkToFloat(memUsed);
m.memory.total = networkToFloat(memTotal);
h.memory.used = buf.readFloat();
h.memory.total = buf.readFloat();
// Disks
if (pos + 1 > buffer.size())
throw std::runtime_error("Buffer too small for disks count");
uint8_t numDisks = buffer[pos++];
for (int i = 0; i < numDisks; ++i)
uint8_t numDisks = buf.readUint8();
h.disks.clear();
h.disks.reserve(numDisks);
for (uint8_t i = 0; i < numDisks; ++i)
{
if (pos + 1 > buffer.size())
throw std::runtime_error("Buffer too small for disk name length");
uint8_t nameLen = buffer[pos++];
if (pos + nameLen + 8 > buffer.size())
throw std::runtime_error("Buffer too small for disk data");
std::string diskName(buffer.begin() + pos, buffer.begin() + pos + nameLen);
pos += nameLen;
uint32_t used, total;
std::memcpy(&used, &buffer[pos], 4);
pos += 4;
std::memcpy(&total, &buffer[pos], 4);
pos += 4;
m.disks.push_back({diskName, networkToFloat(used), networkToFloat(total)});
std::string name = buf.readString();
float used = buf.readFloat();
float total = buf.readFloat();
h.disks.push_back({name, used, total});
}
return m;
return h;
}
} // namespace Metrics
+1 -1
View File
@@ -22,6 +22,6 @@ namespace Metrics
std::vector<uint8_t> serialize() const;
// Десериализация из вектора байт
static Host deserialize(const std::vector<uint8_t> &buffer);
static Host deserialize(const std::vector<uint8_t> &data);
};
} // namespace Metrics
+1
View File
@@ -1,5 +1,6 @@
message(STATUS "·Configuring Network")
add_subdirectory(Common)
if (BUILD_SERVER)
add_subdirectory(Server)
endif()
+86
View File
@@ -0,0 +1,86 @@
#include "Network/Common/Buffer.h"
namespace Network
{
void Buffer::writeUint8(uint8_t v)
{
buffer.push_back(v);
}
void Buffer::writeUint32(uint32_t v)
{
uint32_t net = htonl(v);
auto p = reinterpret_cast<uint8_t *>(&net);
buffer.insert(buffer.end(), p, p + sizeof(net));
}
void Buffer::writeFloat(float f)
{
uint32_t tmp;
static_assert(sizeof(tmp) == sizeof(f), "Size mismatch");
std::memcpy(&tmp, &f, sizeof(f));
writeUint32(tmp);
}
void Buffer::writeBytes(const uint8_t *data, size_t len)
{
buffer.insert(buffer.end(), data, data + len);
}
void Buffer::writeString(const std::string &s)
{
if (s.size() > 255)
throw std::runtime_error("String too long");
writeUint8(static_cast<uint8_t>(s.size()));
writeBytes(reinterpret_cast<const uint8_t *>(s.data()), s.size());
}
// --- Reading ---
uint8_t Buffer::readUint8()
{
checkRemaining(1);
return buffer[pos++];
}
uint32_t Buffer::readUint32()
{
checkRemaining(4);
uint32_t tmp;
std::memcpy(&tmp, &buffer[pos], 4);
pos += 4;
return ntohl(tmp);
}
float Buffer::readFloat()
{
uint32_t tmp = readUint32();
float f;
std::memcpy(&f, &tmp, sizeof(f));
return f;
}
std::string Buffer::readString()
{
uint8_t len = readUint8();
checkRemaining(len);
std::string s(reinterpret_cast<const char *>(&buffer[pos]), len);
pos += len;
return s;
}
size_t Buffer::remaining() const
{
return buffer.size() - pos;
}
std::vector<uint8_t> &Buffer::data()
{
return buffer;
}
void Buffer::checkRemaining(size_t n)
{
if (pos + n > buffer.size())
throw std::runtime_error("Buffer underrun");
}
} // namespace Network
+37
View File
@@ -0,0 +1,37 @@
#pragma once
#include <vector>
#include <cstdint>
#include <cstring>
#include <stdexcept>
#include <arpa/inet.h>
namespace Network
{
class Buffer
{
public:
explicit Buffer(std::vector<uint8_t> &buf) : buffer(buf), pos(0) {}
explicit Buffer(size_t reserve = 0) : buffer(reserve), pos(0) {}
// --- Writing ---
void writeUint8(uint8_t v);
void writeUint32(uint32_t v);
void writeFloat(float f);
void writeBytes(const uint8_t *data, size_t len);
void writeString(const std::string &s);
// --- Reading ---
uint8_t readUint8();
uint32_t readUint32();
float readFloat();
std::string readString();
size_t remaining() const;
std::vector<uint8_t> &data();
private:
void checkRemaining(size_t n);
std::vector<uint8_t> buffer;
size_t pos;
};
} // namespace Network
+10
View File
@@ -0,0 +1,10 @@
add_library(Network.Common
Buffer.cpp
)
add_library(Network::Common ALIAS Network.Common)
target_include_directories(Network.Common
PUBLIC
${INCLUDE_BASE_DIR}
)