Add buffer
This commit is contained in:
@@ -7,6 +7,11 @@ add_library(Metrics
|
|||||||
|
|
||||||
add_library(Metrics::All ALIAS Metrics)
|
add_library(Metrics::All ALIAS Metrics)
|
||||||
|
|
||||||
|
target_link_libraries(Metrics
|
||||||
|
PRIVATE
|
||||||
|
Network::Common
|
||||||
|
)
|
||||||
|
|
||||||
target_include_directories(Metrics
|
target_include_directories(Metrics
|
||||||
PUBLIC
|
PUBLIC
|
||||||
${INCLUDE_BASE_DIR}
|
${INCLUDE_BASE_DIR}
|
||||||
|
|||||||
+38
-93
@@ -4,6 +4,8 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#include "Network/Common/Buffer.h"
|
||||||
|
|
||||||
namespace Metrics
|
namespace Metrics
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -27,126 +29,69 @@ namespace Metrics
|
|||||||
// ---- Сериализация ----
|
// ---- Сериализация ----
|
||||||
std::vector<uint8_t> Host::serialize() const
|
std::vector<uint8_t> Host::serialize() const
|
||||||
{
|
{
|
||||||
std::vector<uint8_t> buffer;
|
Network::Buffer buf;
|
||||||
buffer.push_back(1); // версия протокола
|
|
||||||
|
|
||||||
// Host
|
buf.writeUint8(1); // version
|
||||||
buffer.push_back(static_cast<uint8_t>(hostname.size()));
|
buf.writeString(hostname);
|
||||||
buffer.insert(buffer.end(), hostname.begin(), hostname.end());
|
|
||||||
|
|
||||||
// CPU
|
// CPU
|
||||||
uint32_t totalLoadNet = floatToNetwork(cpu.totalLoad);
|
buf.writeFloat(cpu.totalLoad);
|
||||||
buffer.insert(buffer.end(),
|
buf.writeUint8(static_cast<uint8_t>(cpu.coreLoads.size()));
|
||||||
reinterpret_cast<uint8_t *>(&totalLoadNet),
|
|
||||||
reinterpret_cast<uint8_t *>(&totalLoadNet) + sizeof(totalLoadNet));
|
|
||||||
buffer.push_back(static_cast<uint8_t>(cpu.coreLoads.size()));
|
|
||||||
for (float f : cpu.coreLoads)
|
for (float f : cpu.coreLoads)
|
||||||
{
|
buf.writeFloat(f);
|
||||||
uint32_t net = floatToNetwork(f);
|
|
||||||
buffer.insert(buffer.end(),
|
|
||||||
reinterpret_cast<uint8_t *>(&net),
|
|
||||||
reinterpret_cast<uint8_t *>(&net) + 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Memory
|
// Memory
|
||||||
uint32_t usedNet = floatToNetwork(memory.used);
|
buf.writeFloat(memory.used);
|
||||||
uint32_t totalNet = floatToNetwork(memory.total);
|
buf.writeFloat(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));
|
|
||||||
|
|
||||||
// Disks
|
// Disks
|
||||||
buffer.push_back(static_cast<uint8_t>(disks.size()));
|
buf.writeUint8(static_cast<uint8_t>(disks.size()));
|
||||||
for (const auto &d : disks)
|
for (const auto &d : disks)
|
||||||
{
|
{
|
||||||
buffer.push_back(static_cast<uint8_t>(d.name.size()));
|
buf.writeString(d.name);
|
||||||
buffer.insert(buffer.end(), d.name.begin(), d.name.end());
|
buf.writeFloat(d.used);
|
||||||
|
buf.writeFloat(d.total);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
Host h;
|
||||||
size_t pos = 0;
|
Network::Buffer buf(const_cast<std::vector<uint8_t> &>(data));
|
||||||
if (buffer.size() < 1)
|
|
||||||
throw std::runtime_error("Buffer too small");
|
uint8_t version = buf.readUint8();
|
||||||
uint8_t version = buffer[pos++];
|
|
||||||
if (version != 1)
|
if (version != 1)
|
||||||
throw std::runtime_error("Unsupported protocol version");
|
throw std::runtime_error("Unsupported protocol version");
|
||||||
|
|
||||||
// Host
|
h.hostname = buf.readString();
|
||||||
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;
|
|
||||||
|
|
||||||
// CPU
|
// CPU
|
||||||
uint32_t totolLoad;
|
h.cpu.totalLoad = buf.readFloat();
|
||||||
std::memcpy(&totolLoad, &buffer[pos], 4);
|
uint8_t numCpu = buf.readUint8();
|
||||||
pos += 4;
|
h.cpu.coreLoads.clear();
|
||||||
m.cpu.totalLoad = networkToFloat(totolLoad);
|
h.cpu.coreLoads.reserve(numCpu);
|
||||||
uint8_t numCpu = buffer[pos++];
|
for (uint8_t i = 0; i < numCpu; ++i)
|
||||||
if (pos + numCpu * 4 > buffer.size())
|
h.cpu.coreLoads.push_back(buf.readFloat());
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Memory
|
// Memory
|
||||||
if (pos + 8 > buffer.size())
|
h.memory.used = buf.readFloat();
|
||||||
throw std::runtime_error("Buffer too small for memory");
|
h.memory.total = buf.readFloat();
|
||||||
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);
|
|
||||||
|
|
||||||
// Disks
|
// Disks
|
||||||
if (pos + 1 > buffer.size())
|
uint8_t numDisks = buf.readUint8();
|
||||||
throw std::runtime_error("Buffer too small for disks count");
|
h.disks.clear();
|
||||||
uint8_t numDisks = buffer[pos++];
|
h.disks.reserve(numDisks);
|
||||||
for (int i = 0; i < numDisks; ++i)
|
for (uint8_t i = 0; i < numDisks; ++i)
|
||||||
{
|
{
|
||||||
if (pos + 1 > buffer.size())
|
std::string name = buf.readString();
|
||||||
throw std::runtime_error("Buffer too small for disk name length");
|
float used = buf.readFloat();
|
||||||
uint8_t nameLen = buffer[pos++];
|
float total = buf.readFloat();
|
||||||
if (pos + nameLen + 8 > buffer.size())
|
h.disks.push_back({name, used, total});
|
||||||
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)});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return m;
|
return h;
|
||||||
}
|
}
|
||||||
} // namespace Metrics
|
} // namespace Metrics
|
||||||
+1
-1
@@ -22,6 +22,6 @@ namespace Metrics
|
|||||||
std::vector<uint8_t> serialize() const;
|
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
|
} // namespace Metrics
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
message(STATUS "·Configuring Network")
|
message(STATUS "·Configuring Network")
|
||||||
|
|
||||||
|
add_subdirectory(Common)
|
||||||
if (BUILD_SERVER)
|
if (BUILD_SERVER)
|
||||||
add_subdirectory(Server)
|
add_subdirectory(Server)
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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
|
||||||
@@ -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}
|
||||||
|
)
|
||||||
Reference in New Issue
Block a user