From 0354ce776b715764383ade31137451f37d749f1d Mon Sep 17 00:00:00 2001 From: Persson-dev Date: Sun, 13 Oct 2024 15:30:57 +0200 Subject: [PATCH] declare packets + commands --- include/td/common/DataBuffer.h | 82 ++++----- include/td/common/VarInt.h | 58 +++++++ include/td/misc/Format.h | 38 ++++ include/td/misc/Log.h | 32 ++++ include/td/protocol/ByteBuffer.h | 94 ---------- include/td/protocol/command/CommandData.h | 18 +- include/td/protocol/command/CommandDeclare.h | 9 +- .../td/protocol/command/CommandDispatcher.h | 5 +- include/td/protocol/command/CommandHandler.h | 33 ---- include/td/protocol/command/Commands.h | 3 + include/td/protocol/packet/PacketData.h | 58 +++---- include/td/protocol/packet/PacketDeclare.h | 11 +- include/td/protocol/packet/PacketDispatcher.h | 5 +- include/td/protocol/packet/PacketHandler.h | 33 ---- src/main.cpp | 4 +- src/td/common/DataBuffer.cpp | 162 ++++++++++++++++++ src/td/common/VarInt.cpp | 52 ++++++ src/td/misc/Log.cpp | 37 ++++ 18 files changed, 461 insertions(+), 273 deletions(-) create mode 100644 include/td/common/VarInt.h create mode 100644 include/td/misc/Format.h create mode 100644 include/td/misc/Log.h delete mode 100644 include/td/protocol/ByteBuffer.h delete mode 100644 include/td/protocol/command/CommandHandler.h delete mode 100644 include/td/protocol/packet/PacketHandler.h create mode 100644 src/td/common/DataBuffer.cpp create mode 100644 src/td/common/VarInt.cpp create mode 100644 src/td/misc/Log.cpp diff --git a/include/td/common/DataBuffer.h b/include/td/common/DataBuffer.h index b2fcc89..f471ca8 100644 --- a/include/td/common/DataBuffer.h +++ b/include/td/common/DataBuffer.h @@ -11,6 +11,7 @@ #include #include #include +#include namespace td { @@ -65,19 +66,24 @@ class DataBuffer { * \warning Don't use it for binary data ! * \param str The string to append */ - DataBuffer& operator<<(const std::string& str) { - std::size_t strlen = str.length() + 1; // including null character - Resize(GetSize() + strlen); - std::memcpy(m_Buffer.data() + GetSize() - strlen, str.data(), strlen); - return *this; - } + DataBuffer& operator<<(const std::string& str); /** * \brief Append data to the buffer from another const buffer * \param data The buffer to append */ - DataBuffer& operator<<(const DataBuffer& data) { - m_Buffer.insert(m_Buffer.end(), data.begin(), data.end()); + DataBuffer& operator<<(const DataBuffer& data); + + /** + * \brief Append a vector to the buffer by first writing the size + * \param data The buffer to append + */ + template + DataBuffer& operator<<(const std::vector& data) { + *this << VarInt {data.size()}; + for (const auto& element : data) { + *this << element; + } return *this; } @@ -96,25 +102,28 @@ class DataBuffer { * \brief Read some data from the buffer and assign to the new buffer * \param data The buffer to assign */ - DataBuffer& operator>>(DataBuffer& data) { - data.Resize(GetSize() - m_ReadOffset); - std::copy(m_Buffer.begin() + static_cast(m_ReadOffset), m_Buffer.end(), data.begin()); - m_ReadOffset = m_Buffer.size(); - return *this; - } + DataBuffer& operator>>(DataBuffer& data); /** * \brief Read a string from the buffer * \param str The string to assign in the new buffer * \warning Don't use it for binary data ! */ - DataBuffer& operator>>(std::string& str) { - std::size_t stringSize = - strlen(reinterpret_cast(m_Buffer.data()) + m_ReadOffset) + 1; // including null character - str.resize(stringSize); - std::copy(m_Buffer.begin() + static_cast(m_ReadOffset), - m_Buffer.begin() + static_cast(m_ReadOffset + stringSize), str.begin()); - m_ReadOffset += stringSize; + DataBuffer& operator>>(std::string& str); + + /** + * \brief Read a vector (size + data) from the buffer + * \pre The vector is assumed to be empty + */ + template + DataBuffer& operator>>(std::vector& data) { + VarInt arraySize; + *this >> arraySize; + for (std::size_t i = 0; i < arraySize.GetValue(); i++) { + T newElement; + *this >> newElement; + data.push_back(newElement); + } return *this; } @@ -123,56 +132,35 @@ class DataBuffer { * \param buffer The buffer to write * \param amount The amount of data to write */ - void WriteSome(const char* buffer, std::size_t amount) { - std::size_t end_pos = m_Buffer.size(); - m_Buffer.resize(m_Buffer.size() + amount); - std::memcpy(m_Buffer.data() + end_pos, buffer, amount); - } + void WriteSome(const char* buffer, std::size_t amount); /** * \brief Write some data to the buffer * \param buffer The buffer to write * \param amount The amount of data to write */ - void WriteSome(const std::uint8_t* buffer, std::size_t amount) { - std::size_t end_pos = m_Buffer.size(); - m_Buffer.resize(m_Buffer.size() + amount); - std::memcpy(m_Buffer.data() + end_pos, buffer, amount); - } + void WriteSome(const std::uint8_t* buffer, std::size_t amount); /** * \brief Read some data from the buffer * \param buffer The buffer to Read * \param amount The amount of data from the buffer */ - void ReadSome(char* buffer, std::size_t amount) { - assert(m_ReadOffset + amount <= GetSize()); - std::copy_n(m_Buffer.begin() + static_cast(m_ReadOffset), amount, buffer); - m_ReadOffset += amount; - } + void ReadSome(char* buffer, std::size_t amount); /** * \brief Read some data from the buffer * \param buffer The buffer to Read * \param amount The amount of data from the buffer */ - void ReadSome(std::uint8_t* buffer, std::size_t amount) { - assert(m_ReadOffset + amount <= GetSize()); - std::copy_n(m_Buffer.begin() + static_cast(m_ReadOffset), amount, buffer); - m_ReadOffset += amount; - } + void ReadSome(std::uint8_t* buffer, std::size_t amount); /** * \brief Read some data from the buffer * \param buffer The buffer to Read * \param amount The amount of data from the buffer */ - void ReadSome(DataBuffer& buffer, std::size_t amount) { - assert(m_ReadOffset + amount <= GetSize()); - buffer.Resize(amount); - std::copy_n(m_Buffer.begin() + static_cast(m_ReadOffset), amount, buffer.begin()); - m_ReadOffset += amount; - } + void ReadSome(DataBuffer& buffer, std::size_t amount); /** * \brief Resize the buffer diff --git a/include/td/common/VarInt.h b/include/td/common/VarInt.h new file mode 100644 index 0000000..02c33d5 --- /dev/null +++ b/include/td/common/VarInt.h @@ -0,0 +1,58 @@ +#pragma once + +/** + * \file VarInt.h + * \brief File containing the blitz::VarInt class + */ + +#include +#include + +namespace td { + +class DataBuffer; + +/** + * \class VarInt + * \brief Variable-length format such that smaller numbers use fewer bytes. + */ +class VarInt { + private: + std::uint64_t m_Value; + + public: + VarInt() : m_Value(0) {} + /** + * \brief Construct a variable integer from a value + * \param value The value of the variable integer + */ + VarInt(std::uint64_t value) : m_Value(value) {} + + /** + * \brief Get the value of the variable integer + */ + std::uint64_t GetValue() const { + return m_Value; + } + + /** + * \brief Get the length of the serialized variable integer + */ + std::size_t GetSerializedLength() const; + + /** + * \brief Serialize the variable integer + * \param out The buffer to write the serialized variable integer to + * \param var The variable integer to serialize + */ + friend DataBuffer& operator<<(DataBuffer& out, const VarInt& var); + + /** + * \brief Deserialize the variable integer + * \param in The buffer to read the serialized variable integer from + * \param var The variable integer to deserialize + */ + friend DataBuffer& operator>>(DataBuffer& in, VarInt& var); +}; + +} // namespace td diff --git a/include/td/misc/Format.h b/include/td/misc/Format.h new file mode 100644 index 0000000..b407a38 --- /dev/null +++ b/include/td/misc/Format.h @@ -0,0 +1,38 @@ +#pragma once + +/** + * \file Format.h + * \brief This file contains the definition of the `Format` function. + */ + +#include +#include +#include + +namespace td { +namespace utils { + +/** + * \brief Formats a string using a format string and variadic arguments. + * + * This function takes a format string and a variable number of arguments and returns a formatted string. + * The format string can contain placeholders that will be replaced by the corresponding arguments. + * + * \param format The format string. + * \param args The variadic arguments to be formatted. + * \return The formatted string. + * \throws std::runtime_error if an error occurs during formatting. + */ +template +std::string Format(const std::string& format, Args... args) { + int size = snprintf(nullptr, 0, format.c_str(), args...) + 1; // Extra space for '\0' + if (size <= 0) { + throw std::runtime_error("Error during formatting."); + } + std::unique_ptr buf(new char[size]); + snprintf(buf.get(), static_cast(size), format.c_str(), args...); + return std::string(buf.get(), buf.get() + size - 1); // We don't want the '\0' inside +} + +} // namespace utils +} // namespace td diff --git a/include/td/misc/Log.h b/include/td/misc/Log.h new file mode 100644 index 0000000..042aa80 --- /dev/null +++ b/include/td/misc/Log.h @@ -0,0 +1,32 @@ +#pragma once + +/** + * \file Log.h + * \brief File defining log functions + */ + +#include + +namespace td { +namespace utils { + +/** + * \brief Logs a normal message. + * \param msg The message to be logged. + */ +void LOG(const std::string& msg); + +/** + * \brief Logs a normal message in debug mode. + * \param msg The message to be logged. + */ +void LOGD(const std::string& msg); + +/** + * \brief Logs an error message. + * \param err The error message to be logged. + */ +void LOGE(const std::string& err); + +} // namespace utils +} // namespace td diff --git a/include/td/protocol/ByteBuffer.h b/include/td/protocol/ByteBuffer.h deleted file mode 100644 index 076843c..0000000 --- a/include/td/protocol/ByteBuffer.h +++ /dev/null @@ -1,94 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -namespace td { -namespace protocol { - -class PlayerInfo; - -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); - } - - const godot::PackedByteArray& GetByteArray() const { - return m_Buffer; - } - - godot::PackedByteArray& GetByteArray() { - return m_Buffer; - } - - // Integers - ByteBuffer& operator<<(int8_t a_Data); - ByteBuffer& operator>>(int8_t& a_Data); - ByteBuffer& operator<<(uint8_t a_Data); - ByteBuffer& operator>>(uint8_t& a_Data); - - 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); - - ByteBuffer& operator<<(const godot::Vector3& a_Data); - ByteBuffer& operator>>(godot::Vector3& a_Data); - - template - ByteBuffer& operator<<(const std::vector& a_Data) { - *this << static_cast(a_Data.size()); - for (const T& data : a_Data) { - *this << data; - } - return *this; - } - - template - ByteBuffer& operator>>(std::vector& a_Data) { - std::uint32_t arraySize; - *this >> arraySize; - a_Data.resize(arraySize); - for (std::uint32_t i = 0; i < arraySize; i++) { - *this >> a_Data[i]; - } - return *this; - } - - ByteBuffer& operator<<(const PlayerInfo& a_Data); - ByteBuffer& operator>>(PlayerInfo& a_Data); -}; - -} // namespace protocol -} // namespace td diff --git a/include/td/protocol/command/CommandData.h b/include/td/protocol/command/CommandData.h index f385112..d7c7689 100644 --- a/include/td/protocol/command/CommandData.h +++ b/include/td/protocol/command/CommandData.h @@ -2,25 +2,11 @@ #include #include +#include namespace td { namespace protocol { -#define LOCKSTEP_BUFFER_SIZE 10 - -struct LockStepCommand {}; - -struct LockStep { - std::uint8_t m_CommandNumber; - std::vector m_Commands; -}; - -struct LockSteps { - std::uint16_t m_FirstFrameNumber; - std::array m_LockSteps; -}; - - namespace cdata { @@ -58,6 +44,8 @@ struct PlayerJoin { std::string m_Name; }; +struct End {}; + } // namespace cdata diff --git a/include/td/protocol/command/CommandDeclare.h b/include/td/protocol/command/CommandDeclare.h index 4cf6fde..76013d7 100644 --- a/include/td/protocol/command/CommandDeclare.h +++ b/include/td/protocol/command/CommandDeclare.h @@ -6,15 +6,16 @@ namespace protocol { /** * \def DeclareAllPacket - * \brief Avoids repetitive operations on packets + * \brief Avoids repetitive operations on commands */ #define DeclareAllCommand() \ + DeclareCommand(End) \ DeclareCommand(PlaceTower) \ - DeclareCommand(UpgradeTower) \ + DeclareCommand(PlayerJoin) \ DeclareCommand(SpawnTroop) \ - DeclareCommand(UseItem) \ DeclareCommand(TeamChange) \ - DeclareCommand(PlayerJoin) + DeclareCommand(UpgradeTower) \ + DeclareCommand(UseItem) } // namespace protocol diff --git a/include/td/protocol/command/CommandDispatcher.h b/include/td/protocol/command/CommandDispatcher.h index ca3534f..0dc3ef9 100644 --- a/include/td/protocol/command/CommandDispatcher.h +++ b/include/td/protocol/command/CommandDispatcher.h @@ -6,13 +6,12 @@ */ #include +#include namespace td { namespace protocol { -class CommandHandler; - -using CommandDispatcher = Dispatcher; +using CommandDispatcher = Dispatcher; } // namespace protocol } // namespace td diff --git a/include/td/protocol/command/CommandHandler.h b/include/td/protocol/command/CommandHandler.h deleted file mode 100644 index 8d8e09d..0000000 --- a/include/td/protocol/command/CommandHandler.h +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once - -/** - * \file CommandHandler.h - * \brief File containing the td::protocol::CommandHandler class - */ - -#include -#include - -namespace td { -namespace protocol { - -#define DeclareCommand(CommandName, ...) \ - virtual void Visit(const commands::CommandName&); \ - virtual void HandleCommand(const commands::CommandName&) {} - -/** - * \class CommandHandler - * \brief Class used to handle packets - */ -class CommandHandler : public CommandVisitor { - public: - CommandHandler() {} - ~CommandHandler() {} - - DeclareAllCommand() -}; - -#undef DeclareCommand - -} // namespace protocol -} // namespace td \ No newline at end of file diff --git a/include/td/protocol/command/Commands.h b/include/td/protocol/command/Commands.h index 65495d2..4444d21 100644 --- a/include/td/protocol/command/Commands.h +++ b/include/td/protocol/command/Commands.h @@ -9,6 +9,7 @@ #include #include #include +#include namespace td { namespace protocol { @@ -104,5 +105,7 @@ DeclareAllCommand() } // namespace commands +using LockStep = std::vector>; + } // namespace protocol } // namespace td diff --git a/include/td/protocol/packet/PacketData.h b/include/td/protocol/packet/PacketData.h index 8f86352..fdcfb62 100644 --- a/include/td/protocol/packet/PacketData.h +++ b/include/td/protocol/packet/PacketData.h @@ -2,6 +2,10 @@ #include #include +#include + +// Make it dynamic ? +#define LOCKSTEP_BUFFER_SIZE 10 namespace td { namespace protocol { @@ -11,64 +15,60 @@ struct PlayerInfo { std::string m_PlayerName; }; +struct MapData { + +}; + namespace pdata { +/** Client attempts to login (very basic) */ struct PlayerLogin { std::string m_PlayerName; }; -struct UpdateHealth { - float m_NewHealth; -}; - +/** Server indicates success */ struct LoggingSuccess { PlayerID m_PlayerId; }; -struct PlayerDeath {}; - +/** Player joins the lobby */ struct PlayerJoin { PlayerInfo m_Player; }; +/** Player leaves the lobby */ struct PlayerLeave { PlayerID m_PlayerId; }; -struct PlayerStats {}; - -struct PlayerList { - std::vector m_Players; -}; - -struct ServerConfig {}; - -struct ServerTps {}; - -struct UpdateGameState {}; - +/** Keep alive */ struct KeepAlive { std::uint64_t m_KeepAliveId; }; -struct Disconnect {}; +/** Can be used by both client and server */ +struct Disconnect { + std::string m_Reason; +}; +/** Chat message */ struct ChatMessage { std::string m_Text; }; -struct PlayerPositionAndRotation { - PlayerID m_Player; - // godot::Vector3 m_Position; - // godot::Vector3 m_Rotation; - // godot::Vector3 m_Velocity; +// TODO: handle players joining in the first second + +struct BeginGame { + MapData m_Map; + std::vector m_BlueTeam; + std::vector m_RedTeam; + // optional, used for players joining mid game + std::vector m_FirstLocksteps; }; -struct PlayerShoot { - PlayerID m_Sender; - // godot::Vector3 m_Position; - // godot::Vector3 m_Rotation; - // godot::Vector3 m_Velocity; +struct LockSteps { + std::uint16_t m_FirstFrameNumber; + std::array m_LockSteps; }; } // namespace pdata diff --git a/include/td/protocol/packet/PacketDeclare.h b/include/td/protocol/packet/PacketDeclare.h index 35adbe4..1354d6d 100644 --- a/include/td/protocol/packet/PacketDeclare.h +++ b/include/td/protocol/packet/PacketDeclare.h @@ -34,21 +34,14 @@ enum class PacketSendType { */ #define DeclareAllPacket() \ DeclarePacket(ChatMessage, Reliable, Both) \ + DeclarePacket(BeginGame, Reliable, Server) \ DeclarePacket(Disconnect, Reliable, Both) \ DeclarePacket(KeepAlive, Reliable, Both) \ + DeclarePacket(LockSteps, Unreliable, Both) \ DeclarePacket(LoggingSuccess, Reliable, Server) \ - DeclarePacket(PlayerDeath, Reliable, Server) \ DeclarePacket(PlayerJoin, Reliable, Server) \ DeclarePacket(PlayerLeave, Reliable, Server) \ - DeclarePacket(PlayerList, Reliable, Server) \ DeclarePacket(PlayerLogin, Reliable, Client) \ - DeclarePacket(PlayerPositionAndRotation, Unreliable, Both) \ - DeclarePacket(PlayerShoot, Reliable, Both) \ - DeclarePacket(PlayerStats, Reliable, Server) \ - DeclarePacket(ServerConfig, Reliable, Server) \ - DeclarePacket(ServerTps, Reliable, Server) \ - DeclarePacket(UpdateGameState, Reliable, Server) \ - DeclarePacket(UpdateHealth, Reliable, Client) } // namespace protocol diff --git a/include/td/protocol/packet/PacketDispatcher.h b/include/td/protocol/packet/PacketDispatcher.h index 627e8f4..d0a5d21 100644 --- a/include/td/protocol/packet/PacketDispatcher.h +++ b/include/td/protocol/packet/PacketDispatcher.h @@ -6,13 +6,12 @@ */ #include +#include namespace td { namespace protocol { -class PacketHandler; - -using PacketDispatcher = Dispatcher; +using PacketDispatcher = Dispatcher; } // namespace protocol } // namespace td diff --git a/include/td/protocol/packet/PacketHandler.h b/include/td/protocol/packet/PacketHandler.h deleted file mode 100644 index 8c3b671..0000000 --- a/include/td/protocol/packet/PacketHandler.h +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once - -/** - * \file PacketHandler.h - * \brief File containing the td::protocol::PacketHandler class - */ - -#include -#include - -namespace td { -namespace protocol { - -#define DeclarePacket(PacketName, ...) \ - virtual void Visit(const packets::PacketName&); \ - virtual void HandlePacket(const packets::PacketName&) {} - -/** - * \class PacketHandler - * \brief Class used to handle packets - */ -class PacketHandler : public PacketVisitor { - public: - PacketHandler() {} - ~PacketHandler() {} - - DeclareAllPacket() -}; - -#undef DeclarePacket - -} // namespace protocol -} // namespace td \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index c27958c..75637d9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2,14 +2,12 @@ // #include #include #include -#include #include #include +#include class Test : public td::protocol::CommandVisitor {}; -class Test2 : public td::protocol::CommandHandler {}; - int main(int argc, char** argv) { // Test visitor; // td::protocol::packets::ChatMessage chat{{"coucou"}}; diff --git a/src/td/common/DataBuffer.cpp b/src/td/common/DataBuffer.cpp new file mode 100644 index 0000000..f3e45e3 --- /dev/null +++ b/src/td/common/DataBuffer.cpp @@ -0,0 +1,162 @@ +#include + +#include +#include +#include + +#include +#include + +namespace td { + +DataBuffer::DataBuffer() : m_ReadOffset(0) {} + +DataBuffer::DataBuffer(const DataBuffer& other) : m_Buffer(other.m_Buffer), m_ReadOffset(other.m_ReadOffset) {} + +DataBuffer::DataBuffer(DataBuffer&& other) : m_Buffer(std::move(other.m_Buffer)), m_ReadOffset(std::move(other.m_ReadOffset)) {} + +DataBuffer::DataBuffer(const std::string& str) : m_Buffer(str.begin(), str.end()), m_ReadOffset(0) {} + +DataBuffer::DataBuffer(const DataBuffer& other, Data::difference_type offset) : m_ReadOffset(0) { + m_Buffer.reserve(other.GetSize() - static_cast(offset)); + std::copy(other.m_Buffer.begin() + offset, other.m_Buffer.end(), std::back_inserter(m_Buffer)); +} + +DataBuffer& DataBuffer::operator<<(const std::string& str) { + std::size_t strlen = str.length() + 1; // including null character + Resize(GetSize() + strlen); + std::memcpy(m_Buffer.data() + GetSize() - strlen, str.data(), strlen); + return *this; +} + +DataBuffer& DataBuffer::operator<<(const DataBuffer& data) { + m_Buffer.insert(m_Buffer.end(), data.begin(), data.end()); + return *this; +} + +DataBuffer& DataBuffer::operator>>(std::string& str) { + std::size_t stringSize = strlen(reinterpret_cast(m_Buffer.data()) + m_ReadOffset) + 1; // including null character + str.resize(stringSize); + std::copy(m_Buffer.begin() + static_cast(m_ReadOffset), + m_Buffer.begin() + static_cast(m_ReadOffset + stringSize), str.begin()); + m_ReadOffset += stringSize; + return *this; +} + +DataBuffer& DataBuffer::operator>>(DataBuffer& data) { + data.Resize(GetSize() - m_ReadOffset); + std::copy(m_Buffer.begin() + static_cast(m_ReadOffset), m_Buffer.end(), data.begin()); + m_ReadOffset = m_Buffer.size(); + return *this; +} + +void DataBuffer::WriteSome(const char* buffer, std::size_t amount) { + std::size_t end_pos = m_Buffer.size(); + m_Buffer.resize(m_Buffer.size() + amount); + std::memcpy(m_Buffer.data() + end_pos, buffer, amount); +} + +void DataBuffer::WriteSome(const std::uint8_t* buffer, std::size_t amount) { + std::size_t end_pos = m_Buffer.size(); + m_Buffer.resize(m_Buffer.size() + amount); + std::memcpy(m_Buffer.data() + end_pos, buffer, amount); +} + +void DataBuffer::ReadSome(char* buffer, std::size_t amount) { + assert(m_ReadOffset + amount <= GetSize()); + std::copy_n(m_Buffer.begin() + static_cast(m_ReadOffset), amount, buffer); + m_ReadOffset += amount; +} + + +void DataBuffer::ReadSome(std::uint8_t* buffer, std::size_t amount) { + assert(m_ReadOffset + amount <= GetSize()); + std::copy_n(m_Buffer.begin() + static_cast(m_ReadOffset), amount, buffer); + m_ReadOffset += amount; +} + + +void DataBuffer::ReadSome(DataBuffer& buffer, std::size_t amount) { + assert(m_ReadOffset + amount <= GetSize()); + buffer.Resize(amount); + std::copy_n(m_Buffer.begin() + static_cast(m_ReadOffset), amount, buffer.begin()); + m_ReadOffset += amount; +} + + +DataBuffer& DataBuffer::operator=(const DataBuffer& other) { + m_Buffer = other.m_Buffer; + m_ReadOffset = other.m_ReadOffset; + return *this; +} + +DataBuffer& DataBuffer::operator=(DataBuffer&& other) { + m_Buffer = std::move(other.m_Buffer); + m_ReadOffset = std::move(other.m_ReadOffset); + return *this; +} + +void DataBuffer::SetReadOffset(std::size_t pos) { + assert(pos <= GetSize()); + m_ReadOffset = pos; +} + +std::size_t DataBuffer::GetSize() const { + return m_Buffer.size(); +} + +std::size_t DataBuffer::GetRemaining() const { + return m_Buffer.size() - m_ReadOffset; +} + +DataBuffer::iterator DataBuffer::begin() { + return m_Buffer.begin(); +} + +DataBuffer::iterator DataBuffer::end() { + return m_Buffer.end(); +} + +DataBuffer::const_iterator DataBuffer::begin() const { + return m_Buffer.begin(); +} + +DataBuffer::const_iterator DataBuffer::end() const { + return m_Buffer.end(); +} + +std::ostream& operator<<(std::ostream& os, const DataBuffer& buffer) { + for (unsigned char u : buffer) + os << std::hex << std::setfill('0') << std::setw(2) << static_cast(u) << " "; + os << std::dec; + return os; +} + +bool DataBuffer::ReadFile(const std::string& fileName) { + try { + std::ifstream file(fileName, std::istream::binary); + std::ostringstream ss; + ss << file.rdbuf(); + const std::string& s = ss.str(); + m_Buffer = DataBuffer::Data(s.begin(), s.end()); + m_ReadOffset = 0; + } catch (std::exception& e) { + utils::LOGE(utils::Format("[IO] Failed to read file %s ! reason : %s", fileName.c_str(), e.what())); + return false; + } + return m_Buffer.size() > 0; +} + +bool DataBuffer::WriteFile(const std::string& fileName) const { + try { + std::ofstream file(fileName, std::ostream::binary); + file.write(reinterpret_cast(m_Buffer.data()), static_cast(m_Buffer.size())); + file.flush(); + } catch (std::exception& e) { + utils::LOGE(utils::Format("[IO] Failed to read file %s ! reason : %s", fileName.c_str(), e.what())); + return false; + } + return true; +} + +} // namespace td diff --git a/src/td/common/VarInt.cpp b/src/td/common/VarInt.cpp new file mode 100644 index 0000000..b47bb88 --- /dev/null +++ b/src/td/common/VarInt.cpp @@ -0,0 +1,52 @@ +#include + +#include +#include + +namespace td { + +static constexpr int SEGMENT_BITS = 0x7F; +static constexpr int CONTINUE_BIT = 0x80; + +std::size_t VarInt::GetSerializedLength() const { + DataBuffer buffer; + buffer << *this; + return buffer.GetSize(); +} + +DataBuffer& operator<<(DataBuffer& out, const VarInt& var) { + std::uint64_t value = var.m_Value; + while (true) { + if ((value & ~static_cast(SEGMENT_BITS)) == 0) { + out << static_cast(value); + return out; + } + + out << static_cast((value & SEGMENT_BITS) | CONTINUE_BIT); + + value >>= 7; + } +} + +DataBuffer& operator>>(DataBuffer& in, VarInt& var) { + var.m_Value = 0; + unsigned int position = 0; + std::uint8_t currentByte; + + while (true) { + in.ReadSome(¤tByte, 1); + var.m_Value |= static_cast(currentByte & SEGMENT_BITS) << position; + + if ((currentByte & CONTINUE_BIT) == 0) + break; + + position += 7; + + if (position >= 8 * sizeof(var.m_Value)) + throw std::runtime_error("VarInt is too big"); + } + + return in; +} + +} // namespace td diff --git a/src/td/misc/Log.cpp b/src/td/misc/Log.cpp new file mode 100644 index 0000000..db143a4 --- /dev/null +++ b/src/td/misc/Log.cpp @@ -0,0 +1,37 @@ +#include + + + +#ifdef TD_ANDROID_LOGGING +#include +#else +#include +#endif + +namespace td { +namespace utils { + +void LOG(const std::string& msg) { +#ifdef TD_ANDROID_LOGGING + __android_log_print(ANDROID_LOG_INFO, "TRACKERS", "%s", msg.c_str()); +#else + std::cout << msg << "\n"; +#endif +} + +void LOGD(const std::string& msg) { +#if !defined(NDEBUG) + LOG(msg); +#endif +} + +void LOGE(const std::string& err) { +#ifdef TD_ANDROID_LOGGING + __android_log_print(ANDROID_LOG_ERROR, "TRACKERS", "%s", err.c_str()); +#else + std::cerr << err << "\n"; +#endif +} + +} // namespace utils +} // namespace td