From 9eaef8630fcba2daa7bcabe1e9fabbc7bcb3538e Mon Sep 17 00:00:00 2001 From: Joshua Ashton Date: Sat, 1 Aug 2020 01:49:42 +0100 Subject: [PATCH] Refactor NetworkMessage --- src/NetworkMessage.h | 173 ++++++++++++++----------------------------- src/Protocol.cpp | 6 +- 2 files changed, 58 insertions(+), 121 deletions(-) diff --git a/src/NetworkMessage.h b/src/NetworkMessage.h index c28c03a..dc7d8f4 100644 --- a/src/NetworkMessage.h +++ b/src/NetworkMessage.h @@ -9,116 +9,10 @@ namespace Feather { - class NetworkMessageCounter - { - public: - - inline void WriteVarInt(int32_t value) - { - do { - uint8_t temp = uint8_t(value & 0b01111111); - value >>= 7; - if (value != 0) - temp |= 0b10000000; - - m_size++; - } while (value != 0); - } - - inline void WriteString(const char* string, int32_t length) - { - int32_t stringSize = length + 1; - WriteVarInt(stringSize); - - m_size += stringSize; - } - - inline void WriteLong(int64_t value) - { - m_size += sizeof(int64_t); - } - - inline int32_t GetSize() const { return m_size; } - - private: - int32_t m_size = 0; - }; - class NetworkMessage { public: - - NetworkMessage(int32_t size) - { - NetworkMessageCounter packetSizeCounter; - packetSizeCounter.WriteVarInt(size); - - size_t initialSize = size_t(size) + size_t(packetSizeCounter.GetSize()); - - m_data.reserve(initialSize); - WriteVarInt(size); - } - - inline void WriteVarInt(int32_t value) - { - do { - uint8_t temp = uint8_t(value & 0b01111111); - value >>= 7; - if (value != 0) - temp |= 0b10000000; - - m_data.push_back(temp); - } while (value != 0); - } - - inline void WriteString(const char* string, int32_t length) - { - int32_t stringSize = length + 1; - WriteVarInt(stringSize); - - size_t oldSize = m_data.size(); - size_t newSize = oldSize + size_t(stringSize); - m_data.resize(newSize); - std::memcpy(&m_data[oldSize], string, size_t(stringSize)); - } - - inline void WriteLong(int64_t value) - { - size_t oldSize = m_data.size(); - m_data.resize(oldSize + sizeof(int64_t)); - // TODO: do this with registers if faster (see libcore.io.Memory.pokeLong) - std::memcpy(&m_data[oldSize], &value, sizeof(int64_t)); - } - - inline virtual const uint8_t* GetData() const { return m_data.data(); } - inline virtual size_t GetDataSize() const { return m_data.size(); } - - protected: - // Used by subclasses with their own constructors - NetworkMessage() {} - - std::vector m_data; - }; - - #define DEFINE_MESSAGE_WRAPPER(x) \ - template \ - NetworkMessage x(Args... args) \ - { \ - NetworkMessageCounter counter; \ - x(counter, args...); \ - NetworkMessage message(counter.GetSize()); \ - x(message, args...); \ - return message; \ - } - - // This class provides an alternative to NetworkMessageCounter, instead performing - // one count and prepending the size marker to the start of the buffer. - // - // To do this, you must call Finalize() before GetDataSize() or GetData() - class DynamicNetworkMessage : public NetworkMessage - { - public: - DynamicNetworkMessage(int32_t expectedSize) : NetworkMessage() + NetworkMessage(int32_t expectedSize) { size_t initialSize = VARINT_MAX_SIZE + expectedSize; @@ -126,39 +20,84 @@ namespace Feather m_data.resize(VARINT_MAX_SIZE); } - void Finalize() + template + inline void WriteData(const T* data, size_t size) + { + size_t offset = m_data.size(); + + m_data.resize(offset + size); + std::memcpy(&m_data[offset], data, size); + } + + template + inline void Write(const T& value) + { + // Todo: Endian-ness + WriteData(&value, sizeof(T)); + } + + inline void WriteVarInt(int32_t value) + { + do { + uint8_t temp = uint8_t(value & 0b01111111); + value >>= 7; + if (value != 0) + temp |= 0b10000000; + + Write(temp); + } while (value != 0); + } + + inline void WriteString(const char* string, int32_t length) + { + int32_t stringSize = length + 1; + WriteVarInt(stringSize); + WriteData(string, stringSize); + } + + inline void Finalize() { PrependVarIntSize(); +#ifdef _DEBUG m_finalized = true; +#endif } // Inlining and 'final' should ideally avert vtable lookups // TOOD: Make these separate functions if vtable is not averted - inline virtual const uint8_t* GetData() const final + inline const uint8_t* GetData() const { +#ifdef _DEBUG // You must call Finalize() first assert(m_finalized); - return m_data.data() + m_startOffset; +#endif + return &m_data[m_startOffset]; } - inline virtual size_t GetDataSize() const final + inline size_t GetDataSize() const { +#ifdef _DEBUG // You must call Finalize() first assert(m_finalized); +#endif return m_data.size() - m_startOffset; } + private: - int m_startOffset = 0; + std::vector m_data; + size_t m_startOffset = 0; +#ifdef _DEBUG bool m_finalized = false; +#endif void PrependVarIntSize() { uint8_t sizeBytes[VARINT_MAX_SIZE]; // compute the size of the packet excluding the size marker - int value = int(m_data.size() - VARINT_MAX_SIZE); - int index = 0; + int32_t value = static_cast(m_data.size() - VARINT_MAX_SIZE); + size_t index = 0; // perform WriteVarInt into the static buffer sizeBytes do { @@ -173,13 +112,11 @@ namespace Feather // where to start writing the size marker // if we used all 5 bytes, this is zero // if we used 3 bytes, this would be 2 - int startIndex = VARINT_MAX_SIZE - index; + size_t startIndex = VARINT_MAX_SIZE - index; // Copy sizeBytes into our actual buffer, but align it to the right - for (int i = 0; i < index; i++) - { + for (size_t i = 0; i < index; i++) m_data[startIndex + i] = sizeBytes[i]; - } m_startOffset = startIndex; } diff --git a/src/Protocol.cpp b/src/Protocol.cpp index 1751e96..b1e4b09 100644 --- a/src/Protocol.cpp +++ b/src/Protocol.cpp @@ -79,7 +79,7 @@ namespace Feather { printf("[Protocol] Client sent STATUS_PING_REQUEST\n"); - DynamicNetworkMessage msg(VARINT_MAX_SIZE + json_template.length()); + NetworkMessage msg(VARINT_MAX_SIZE + json_template.length()); // Packet ID msg.WriteVarInt(0); // JSON Contents @@ -94,10 +94,10 @@ namespace Feather int64_t timestamp = packet.Read(); printf("[Protocol] Client sent STATUS_PING: %lld\n", timestamp); - DynamicNetworkMessage msg(VARINT_MAX_SIZE + sizeof(int64_t)); + NetworkMessage msg(VARINT_MAX_SIZE + sizeof(int64_t)); msg.WriteVarInt(1); - msg.WriteLong(timestamp); + msg.Write(timestamp); msg.Finalize(); client.SendMessage(msg);