ByteBuffer: handle read errors

This commit is contained in:
2024-08-20 18:51:01 +02:00
parent a092f6fbc1
commit f557d0dd2d
3 changed files with 64 additions and 27 deletions

View File

@@ -2,6 +2,7 @@
#include <godot_cpp/variant/packed_byte_array.hpp>
#include <godot_cpp/variant/string.hpp>
#include <stdexcept>
#include <vector>
namespace blitz {
@@ -9,25 +10,17 @@ namespace protocol {
class PlayerInfo;
#define Operators(Type, GodotType) \
ByteBuffer& operator>>(Type& a_Data) { \
a_Data = m_Buffer.decode_##GodotType(m_ReadOffset); \
m_ReadOffset += sizeof(a_Data); \
return *this; \
} \
\
ByteBuffer& operator<<(Type a_Data) { \
m_Buffer.resize(m_Buffer.size() + sizeof(a_Data)); \
m_Buffer.encode_##GodotType(m_Buffer.size() - sizeof(a_Data), a_Data); \
return *this; \
}
class ByteBuffer {
private:
godot::PackedByteArray m_Buffer;
std::size_t m_ReadOffset;
public:
class ReadError : public std::runtime_error {
public:
ReadError(const std::string& msg) : std::runtime_error(msg) {}
};
ByteBuffer(godot::PackedByteArray&& a_Buffer) : m_Buffer(std::move(a_Buffer)), m_ReadOffset(0) {}
ByteBuffer() : m_ReadOffset(0) {
m_Buffer.resize(0);
@@ -42,18 +35,30 @@ class ByteBuffer {
}
// Integers
Operators(int8_t, s8);
Operators(uint8_t, u8);
Operators(int16_t, s16);
Operators(uint16_t, u16);
Operators(int32_t, s32);
Operators(uint32_t, u32);
Operators(int64_t, s64);
Operators(uint64_t, u64);
ByteBuffer& operator<<(int8_t a_Data);
ByteBuffer& operator>>(int8_t& a_Data);
ByteBuffer& operator<<(uint8_t a_Data);
ByteBuffer& operator>>(uint8_t& a_Data);
// Reals
Operators(float, float);
Operators(double, double);
ByteBuffer& operator<<(int16_t a_Data);
ByteBuffer& operator>>(int16_t& a_Data);
ByteBuffer& operator<<(uint16_t a_Data);
ByteBuffer& operator>>(uint16_t& a_Data);
ByteBuffer& operator<<(int32_t a_Data);
ByteBuffer& operator>>(int32_t& a_Data);
ByteBuffer& operator<<(uint32_t a_Data);
ByteBuffer& operator>>(uint32_t& a_Data);
ByteBuffer& operator<<(int64_t a_Data);
ByteBuffer& operator>>(int64_t& a_Data);
ByteBuffer& operator<<(uint64_t a_Data);
ByteBuffer& operator>>(uint64_t& a_Data);
ByteBuffer& operator<<(float a_Data);
ByteBuffer& operator>>(float& a_Data);
ByteBuffer& operator<<(double a_Data);
ByteBuffer& operator>>(double& a_Data);
ByteBuffer& operator<<(const godot::String& a_Data);
ByteBuffer& operator>>(godot::String& a_Data);

View File

@@ -5,6 +5,36 @@
namespace blitz {
namespace protocol {
#define Operators(Type, GodotType) \
ByteBuffer& ByteBuffer::operator>>(Type& a_Data) { \
if (sizeof(a_Data) + m_ReadOffset > m_Buffer.size()) { \
throw ReadError("Buffer is too small ! Can't read " #Type); \
} \
a_Data = m_Buffer.decode_##GodotType(m_ReadOffset); \
m_ReadOffset += sizeof(a_Data); \
return *this; \
} \
\
ByteBuffer& ByteBuffer::operator<<(Type a_Data) { \
m_Buffer.resize(m_Buffer.size() + sizeof(a_Data)); \
m_Buffer.encode_##GodotType(m_Buffer.size() - sizeof(a_Data), a_Data); \
return *this; \
}
// Integers
Operators(int8_t, s8);
Operators(uint8_t, u8);
Operators(int16_t, s16);
Operators(uint16_t, u16);
Operators(int32_t, s32);
Operators(uint32_t, u32);
Operators(int64_t, s64);
Operators(uint64_t, u64);
// Reals
Operators(float, float);
Operators(double, double);
ByteBuffer& ByteBuffer::operator>>(PlayerInfo& a_Data) {
*this >> a_Data.m_PlayerId >> a_Data.m_PlayerName;
return *this;
@@ -27,9 +57,9 @@ ByteBuffer& ByteBuffer::operator>>(godot::Vector3& a_Data) {
ByteBuffer& ByteBuffer::operator>>(godot::String& a_Data) {
int nullPos = m_Buffer.find(0, m_ReadOffset);
// TODO: error handling
if (nullPos < 0)
return *this;
throw ReadError("String does not have an and in buffer !");
godot::PackedByteArray stringBuffer = m_Buffer.slice(m_ReadOffset, nullPos);
a_Data = stringBuffer.get_string_from_utf8();

View File

@@ -68,7 +68,8 @@ class Deserializer : public PacketVisitor {
bool Deserialize(const PacketPtr& a_Packet) {
try {
Check(*a_Packet.get());
} catch (std::exception& e) {
} catch (ByteBuffer::ReadError& e) {
godot::UtilityFunctions::printerr("[PacketSerializer::Deserializer] ", e.what());
return false;
}
return true;
@@ -109,6 +110,7 @@ std::unique_ptr<Packet> Deserialize(godot::PackedByteArray& a_Data) {
const PacketPtr& emptyPacket = PacketFactory::CreateReadOnlyPacket(packetType);
Deserializer deserializer(std::move(stream));
if (deserializer.Deserialize(emptyPacket)) {
PacketPtr packet = std::move(deserializer.GetPacket());
return packet;