From e4fc8d35437266cecf8b68df0b4a6680a254c281 Mon Sep 17 00:00:00 2001 From: Keyboard Destroyer Date: Wed, 28 May 2025 23:51:28 +0300 Subject: [PATCH 01/47] Pref draft --- tests/performance/CMakeLists.txt | 5 ++++ tests/performance/perf_serialization.cpp | 29 ++++++++++++++++++++++++ tests/performance/perftest.hpp | 6 +++++ 3 files changed, 40 insertions(+) create mode 100644 tests/performance/CMakeLists.txt create mode 100644 tests/performance/perf_serialization.cpp create mode 100644 tests/performance/perftest.hpp diff --git a/tests/performance/CMakeLists.txt b/tests/performance/CMakeLists.txt new file mode 100644 index 0000000..a0b015c --- /dev/null +++ b/tests/performance/CMakeLists.txt @@ -0,0 +1,5 @@ +project ("AxonEngine.tests.performance") + +set (LIST_LIBRARIES networking) +list_all_tests("perf_*.cpp" ${LIST_LIBRARIES}) +include_directories("../../libraries") diff --git a/tests/performance/perf_serialization.cpp b/tests/performance/perf_serialization.cpp new file mode 100644 index 0000000..139f8f2 --- /dev/null +++ b/tests/performance/perf_serialization.cpp @@ -0,0 +1,29 @@ +#include +#include + +#include +#include +#include + + +int main (int __argc, char* __argv[]) { + const char buffer[] = "Hello World!"; + + const std::chrono::time_point start = std::chrono::system_clock::now(); + + size64_t total; + const char* result = serialize(buffer, sizeof(buffer), 2, &total); + + const std::chrono::time_point end = std::chrono::system_clock::now(); + std::cout << + std::left << std::setw(50) << "Execution time: " << + std::chrono::duration_cast ( end - start ).count() << "ns" << std::endl << + std::setw(50) << "Serialization allocated " << total << " bytes of memory" + << std::endl; + + for (size64_t i = 0; i < total; i++) { + std::cout << std::setw(15) << std::bitset<8>( result[i] ) << std::setw(5) << result[i] << std::setw(5) << static_cast(result[i]) << std::endl; + } + + return 0; +} diff --git a/tests/performance/perftest.hpp b/tests/performance/perftest.hpp new file mode 100644 index 0000000..2738dca --- /dev/null +++ b/tests/performance/perftest.hpp @@ -0,0 +1,6 @@ +#pragma once + +#include +#define PERF_INIT time_t timestamp = 0; +#define PERF_START \ + timestamp = std::chrono:: From a43f928522411869ae5284d07c755e6f69de359b Mon Sep 17 00:00:00 2001 From: KbrdDestroyer Date: Thu, 29 May 2025 16:43:40 +0300 Subject: [PATCH 02/47] MemoryGuard added for memleak tests --- tests/performance/perf_serialization.cpp | 30 +++++- tests/performance/perftest.hpp | 130 ++++++++++++++++++++++- 2 files changed, 153 insertions(+), 7 deletions(-) diff --git a/tests/performance/perf_serialization.cpp b/tests/performance/perf_serialization.cpp index 139f8f2..057c07b 100644 --- a/tests/performance/perf_serialization.cpp +++ b/tests/performance/perf_serialization.cpp @@ -1,3 +1,5 @@ +#include "perftest.hpp" + #include #include @@ -6,8 +8,13 @@ #include -int main (int __argc, char* __argv[]) { - const char buffer[] = "Hello World!"; +#define ENABLE_GUARD MemoryGuard::Singleton()->enableGuard() +#define DISABLE_GUARD MemoryGuard::Singleton()->disableGuard() + +int main () { + ENABLE_GUARD; + + constexpr char buffer[] = "Hello World! Some big data here is awaiting serialization"; const std::chrono::time_point start = std::chrono::system_clock::now(); @@ -15,6 +22,7 @@ int main (int __argc, char* __argv[]) { const char* result = serialize(buffer, sizeof(buffer), 2, &total); const std::chrono::time_point end = std::chrono::system_clock::now(); + DISABLE_GUARD; std::cout << std::left << std::setw(50) << "Execution time: " << std::chrono::duration_cast ( end - start ).count() << "ns" << std::endl << @@ -24,6 +32,22 @@ int main (int __argc, char* __argv[]) { for (size64_t i = 0; i < total; i++) { std::cout << std::setw(15) << std::bitset<8>( result[i] ) << std::setw(5) << result[i] << std::setw(5) << static_cast(result[i]) << std::endl; } - + ENABLE_GUARD; + free((void*) result); return 0; } + +__attribute__((destructor)) +void destroy() { + if (!MemoryGuard::Singleton()->empty()) { + std::cout << "Guard detected memory leak!" << std::endl; + + GuardNode* node = MemoryGuard::Singleton()->getHead(); + MemoryGuard::Singleton()->disableGuard(); + + while (node) { + std::cout << node->ptr << " " << node->size_allocated << std::endl; + node = node->next; + } + } +} \ No newline at end of file diff --git a/tests/performance/perftest.hpp b/tests/performance/perftest.hpp index 2738dca..a15d15f 100644 --- a/tests/performance/perftest.hpp +++ b/tests/performance/perftest.hpp @@ -1,6 +1,128 @@ #pragma once +#if defined(__unix__) +#include +#include -#include -#define PERF_INIT time_t timestamp = 0; -#define PERF_START \ - timestamp = std::chrono:: + +extern "C" void* (*real_malloc) (size_t) = nullptr; +extern "C" void* (*real_calloc) (size_t, size_t) = nullptr; +extern "C" void* (*real_realloc) (void*, size_t) = nullptr; +extern "C" void (*real_free) (void*) = nullptr; + +__attribute__((constructor)) +static void init_hooks() { + real_malloc = (void* (*) (size_t)) dlsym(RTLD_NEXT, "malloc"); + real_calloc = (void* (*) (size_t, size_t)) dlsym(RTLD_NEXT, "calloc"); + real_realloc = (void* (*) (void*, size_t)) dlsym(RTLD_NEXT, "realloc"); + real_free = (void (*) (void*)) dlsym(RTLD_NEXT, "free"); +} + +struct GuardNode { + void* ptr = nullptr; + size_t size_allocated = 0; + GuardNode* next = nullptr; +}; + +class MemoryGuard { +public: + MemoryGuard() { + if (! real_malloc || ! real_free) + init_hooks(); + } + + ~MemoryGuard() { + while (head) { + GuardNode* dummy = head; + head = head->next; + real_free(dummy->ptr); + real_free(dummy); + } + } + + void enableGuard() { isEnabled = true; } + void disableGuard() { isEnabled = false; } + + void insert(void* ptr, size_t size) { + if (!isEnabled) return; + + GuardNode* node = (GuardNode*) real_malloc(sizeof(GuardNode)); + node->next = head; + node->ptr = ptr; + node->size_allocated = size; + + head = node; + } + + void pop(void* ptr) { + GuardNode* node = head; + + if (!node) return; + if (node->ptr == ptr) { + head = node->next; + real_free(node); + return; + } + while (node->next && node->next->ptr != ptr) node = node->next; + if (!node->next) return; + + GuardNode* dummy = node->next; + node->next = node->next->next; + real_free(dummy); + } + + bool empty() { return head == nullptr; } + + static MemoryGuard* Singleton() { + static MemoryGuard g_guard; + return &g_guard; + } + + [[nodiscard]] size_t allocated() const noexcept { + GuardNode *node = head; + size_t acc = 0; + while (node) { + acc += node->size_allocated; + node = node->next; + } + return acc; + } + +private: + GuardNode* head = nullptr; + bool isEnabled = false; +}; + +extern "C" void* malloc(size_t size) noexcept { + if (!real_malloc) + init_hooks(); + void *ptr = real_malloc(size); + MemoryGuard::Singleton()->insert(ptr, size); + return ptr; +} + +extern "C" void *calloc(size_t nmem, size_t size) noexcept { + if (!real_calloc) + init_hooks(); + + void *ptr = real_calloc(nmem, size); + MemoryGuard::Singleton()->insert(ptr, nmem * size); + return ptr; +} + +extern "C" void *realloc(void *ptr, size_t size) noexcept { + if (!real_realloc) + init_hooks(); + + ptr = real_realloc(ptr, size); + MemoryGuard::Singleton()->insert(ptr, size); + return ptr; +} + +extern "C" void free(void *ptr) noexcept { + if (!real_free) + init_hooks(); + MemoryGuard::Singleton()->pop(ptr); + real_free(ptr); +} + +#endif From 84f291ecf2e584c33dea36cf7e70d01981509574 Mon Sep 17 00:00:00 2001 From: KbrdDestroyer Date: Thu, 29 May 2025 16:54:20 +0300 Subject: [PATCH 03/47] MemoryGuard added for memleak tests --- tests/performance/perf_serialization.cpp | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/tests/performance/perf_serialization.cpp b/tests/performance/perf_serialization.cpp index 057c07b..f626316 100644 --- a/tests/performance/perf_serialization.cpp +++ b/tests/performance/perf_serialization.cpp @@ -33,21 +33,17 @@ int main () { std::cout << std::setw(15) << std::bitset<8>( result[i] ) << std::setw(5) << result[i] << std::setw(5) << static_cast(result[i]) << std::endl; } ENABLE_GUARD; - free((void*) result); return 0; } __attribute__((destructor)) void destroy() { if (!MemoryGuard::Singleton()->empty()) { - std::cout << "Guard detected memory leak!" << std::endl; - - GuardNode* node = MemoryGuard::Singleton()->getHead(); + std::cout << std::endl; + std::cerr << "MemoryGuard detected memory leak!" << std::endl; MemoryGuard::Singleton()->disableGuard(); - - while (node) { - std::cout << node->ptr << " " << node->size_allocated << std::endl; - node = node->next; - } - } + std::cerr << "Leaked " << MemoryGuard::Singleton()->allocated() << " bytes of memory :c" << std::endl; + std::cerr << "For more information, add breakpoint into guard hook functions and see, what causes memory leak" + << std::endl; + } } \ No newline at end of file From 6f76e72c3994f373b9073600f7615e07eb38e052 Mon Sep 17 00:00:00 2001 From: KbrdDestroyer Date: Fri, 30 May 2025 11:58:01 +0300 Subject: [PATCH 04/47] MemoryGuard added for memleak tests. Hooks moved to C, Memguard is now CPP class --- examples/basics/basic-synapse/server.cpp | 2 +- tests/performance/CMakeLists.txt | 4 +- tests/performance/perf_serialization.cpp | 26 +--- tests/performance/perftest.hpp | 128 ------------------ tests/utils/CMakeLists.txt | 1 + tests/utils/testutils/CMakeLists.txt | 12 ++ .../testutils/MemoryGuard/MemoryGuard.cpp | 78 +++++++++++ .../testutils/MemoryGuard/MemoryGuard.hpp | 62 +++++++++ tests/utils/testutils/MemoryGuard/memutils.c | 44 ++++++ tests/utils/testutils/MemoryGuard/memutils.h | 19 +++ 10 files changed, 226 insertions(+), 150 deletions(-) delete mode 100644 tests/performance/perftest.hpp create mode 100644 tests/utils/CMakeLists.txt create mode 100644 tests/utils/testutils/CMakeLists.txt create mode 100644 tests/utils/testutils/MemoryGuard/MemoryGuard.cpp create mode 100644 tests/utils/testutils/MemoryGuard/MemoryGuard.hpp create mode 100644 tests/utils/testutils/MemoryGuard/memutils.c create mode 100644 tests/utils/testutils/MemoryGuard/memutils.h diff --git a/examples/basics/basic-synapse/server.cpp b/examples/basics/basic-synapse/server.cpp index 8d9e39a..cb87b66 100644 --- a/examples/basics/basic-synapse/server.cpp +++ b/examples/basics/basic-synapse/server.cpp @@ -31,7 +31,7 @@ void onMessageReceived(const Networking::SynapseMessageReceivedEvent& event) int main() { - Networking::Synapse serverConnection(10423); + Networking::AsyncSynapse serverConnection(10423); serverConnection.getEventManager().subscribe(onMessageReceived); std::cout << "Starting Synapse connection" << std::endl; diff --git a/tests/performance/CMakeLists.txt b/tests/performance/CMakeLists.txt index a0b015c..a03e6f5 100644 --- a/tests/performance/CMakeLists.txt +++ b/tests/performance/CMakeLists.txt @@ -1,5 +1,7 @@ project ("AxonEngine.tests.performance") -set (LIST_LIBRARIES networking) +set (LIST_LIBRARIES networking testutils) list_all_tests("perf_*.cpp" ${LIST_LIBRARIES}) include_directories("../../libraries") +include_directories("../utils/testutils") + diff --git a/tests/performance/perf_serialization.cpp b/tests/performance/perf_serialization.cpp index f626316..306af34 100644 --- a/tests/performance/perf_serialization.cpp +++ b/tests/performance/perf_serialization.cpp @@ -1,4 +1,4 @@ -#include "perftest.hpp" +#include #include #include @@ -7,13 +7,8 @@ #include #include - -#define ENABLE_GUARD MemoryGuard::Singleton()->enableGuard() -#define DISABLE_GUARD MemoryGuard::Singleton()->disableGuard() - int main () { - ENABLE_GUARD; - + ENABLE_MEMGUARD constexpr char buffer[] = "Hello World! Some big data here is awaiting serialization"; const std::chrono::time_point start = std::chrono::system_clock::now(); @@ -22,7 +17,7 @@ int main () { const char* result = serialize(buffer, sizeof(buffer), 2, &total); const std::chrono::time_point end = std::chrono::system_clock::now(); - DISABLE_GUARD; + DISABLE_MEMGUARD std::cout << std::left << std::setw(50) << "Execution time: " << std::chrono::duration_cast ( end - start ).count() << "ns" << std::endl << @@ -32,18 +27,9 @@ int main () { for (size64_t i = 0; i < total; i++) { std::cout << std::setw(15) << std::bitset<8>( result[i] ) << std::setw(5) << result[i] << std::setw(5) << static_cast(result[i]) << std::endl; } - ENABLE_GUARD; + ENABLE_MEMGUARD + free((void*) result); return 0; } -__attribute__((destructor)) -void destroy() { - if (!MemoryGuard::Singleton()->empty()) { - std::cout << std::endl; - std::cerr << "MemoryGuard detected memory leak!" << std::endl; - MemoryGuard::Singleton()->disableGuard(); - std::cerr << "Leaked " << MemoryGuard::Singleton()->allocated() << " bytes of memory :c" << std::endl; - std::cerr << "For more information, add breakpoint into guard hook functions and see, what causes memory leak" - << std::endl; - } -} \ No newline at end of file +MEMGUARD_REPORT \ No newline at end of file diff --git a/tests/performance/perftest.hpp b/tests/performance/perftest.hpp deleted file mode 100644 index a15d15f..0000000 --- a/tests/performance/perftest.hpp +++ /dev/null @@ -1,128 +0,0 @@ -#pragma once -#if defined(__unix__) -#include -#include - - -extern "C" void* (*real_malloc) (size_t) = nullptr; -extern "C" void* (*real_calloc) (size_t, size_t) = nullptr; -extern "C" void* (*real_realloc) (void*, size_t) = nullptr; -extern "C" void (*real_free) (void*) = nullptr; - -__attribute__((constructor)) -static void init_hooks() { - real_malloc = (void* (*) (size_t)) dlsym(RTLD_NEXT, "malloc"); - real_calloc = (void* (*) (size_t, size_t)) dlsym(RTLD_NEXT, "calloc"); - real_realloc = (void* (*) (void*, size_t)) dlsym(RTLD_NEXT, "realloc"); - real_free = (void (*) (void*)) dlsym(RTLD_NEXT, "free"); -} - -struct GuardNode { - void* ptr = nullptr; - size_t size_allocated = 0; - GuardNode* next = nullptr; -}; - -class MemoryGuard { -public: - MemoryGuard() { - if (! real_malloc || ! real_free) - init_hooks(); - } - - ~MemoryGuard() { - while (head) { - GuardNode* dummy = head; - head = head->next; - real_free(dummy->ptr); - real_free(dummy); - } - } - - void enableGuard() { isEnabled = true; } - void disableGuard() { isEnabled = false; } - - void insert(void* ptr, size_t size) { - if (!isEnabled) return; - - GuardNode* node = (GuardNode*) real_malloc(sizeof(GuardNode)); - node->next = head; - node->ptr = ptr; - node->size_allocated = size; - - head = node; - } - - void pop(void* ptr) { - GuardNode* node = head; - - if (!node) return; - if (node->ptr == ptr) { - head = node->next; - real_free(node); - return; - } - while (node->next && node->next->ptr != ptr) node = node->next; - if (!node->next) return; - - GuardNode* dummy = node->next; - node->next = node->next->next; - real_free(dummy); - } - - bool empty() { return head == nullptr; } - - static MemoryGuard* Singleton() { - static MemoryGuard g_guard; - return &g_guard; - } - - [[nodiscard]] size_t allocated() const noexcept { - GuardNode *node = head; - size_t acc = 0; - while (node) { - acc += node->size_allocated; - node = node->next; - } - return acc; - } - -private: - GuardNode* head = nullptr; - bool isEnabled = false; -}; - -extern "C" void* malloc(size_t size) noexcept { - if (!real_malloc) - init_hooks(); - void *ptr = real_malloc(size); - MemoryGuard::Singleton()->insert(ptr, size); - return ptr; -} - -extern "C" void *calloc(size_t nmem, size_t size) noexcept { - if (!real_calloc) - init_hooks(); - - void *ptr = real_calloc(nmem, size); - MemoryGuard::Singleton()->insert(ptr, nmem * size); - return ptr; -} - -extern "C" void *realloc(void *ptr, size_t size) noexcept { - if (!real_realloc) - init_hooks(); - - ptr = real_realloc(ptr, size); - MemoryGuard::Singleton()->insert(ptr, size); - return ptr; -} - -extern "C" void free(void *ptr) noexcept { - if (!real_free) - init_hooks(); - MemoryGuard::Singleton()->pop(ptr); - real_free(ptr); -} - -#endif diff --git a/tests/utils/CMakeLists.txt b/tests/utils/CMakeLists.txt new file mode 100644 index 0000000..fe10b99 --- /dev/null +++ b/tests/utils/CMakeLists.txt @@ -0,0 +1 @@ +add_all_subdirs() \ No newline at end of file diff --git a/tests/utils/testutils/CMakeLists.txt b/tests/utils/testutils/CMakeLists.txt new file mode 100644 index 0000000..3bd04bc --- /dev/null +++ b/tests/utils/testutils/CMakeLists.txt @@ -0,0 +1,12 @@ +file(GLOB_RECURSE SOURCES + "${CMAKE_CURRENT_SOURCE_DIR}/*.c" + "${CMAKE_CURRENT_SOURCE_DIR}/*.h" + "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/*.hpp" + "${CMAKE_CURRENT_SOURCE_DIR}/*.ipp" +) + +add_library(testutils STATIC ${SOURCES}) +set (LIB_HOME ${CMAKE_HOME_DIRECTORY}/test/utils/testutils) + +target_include_directories(networking PUBLIC "${LIB_HOME}") diff --git a/tests/utils/testutils/MemoryGuard/MemoryGuard.cpp b/tests/utils/testutils/MemoryGuard/MemoryGuard.cpp new file mode 100644 index 0000000..7100f4a --- /dev/null +++ b/tests/utils/testutils/MemoryGuard/MemoryGuard.cpp @@ -0,0 +1,78 @@ +#include "MemoryGuard.hpp" + +#if defined(__unix) || defined(__unix__) +extern "C" void init_hooks(); +extern void* (*real_malloc) (size_t); +extern void* (*real_calloc) (size_t, size_t); +extern void* (*real_realloc) (void*, size_t); +extern void (*real_free) (void*); + +void add_to_guard(void *ptr, size_t size) { + Testing::MemoryGuard::instance()->insert(ptr, size); +} + +void remove_from_guard(void *ptr) { + Testing::MemoryGuard::instance()->pop(ptr); +} + +namespace Testing { + MemoryGuard::MemoryGuard() { + init_hooks(); + } + + MemoryGuard::~MemoryGuard() { + while (head) { + MemoryNode *dummy = head; + head = head->next; + real_free(head); + } + } + + void MemoryGuard::insert(void *ptr, size_t size) { + if (!isEnabled) return; + + MemoryNode *node = reinterpret_cast(real_malloc(sizeof(MemoryNode))); + node->ptr = ptr; + node->size = size; + node->next = head; + head = node; + } + + void MemoryGuard::pop(void *ptr) { + if (!head) return; + if (head->ptr == ptr) { + // Remove if already on head + MemoryNode* dummy = head; + head = head->next; + real_free(dummy); + return; + } + + MemoryNode *node = head; + while (node->next && node->next->ptr != ptr) node = node->next; + + if (!node->next) return; // Not found + + // Remove + MemoryNode* dummy = node->next; + node->next = node->next->next; + real_free(dummy); + } + + size_t MemoryGuard::total() const { + size_t total = 0; + MemoryNode *node = head; + while (node) { + total += node->size; + node = node->next; + } + + return total; + } + + MemoryGuard *MemoryGuard::instance() { + static MemoryGuard g_guard; + return &g_guard; + } +} // Testing +#endif diff --git a/tests/utils/testutils/MemoryGuard/MemoryGuard.hpp b/tests/utils/testutils/MemoryGuard/MemoryGuard.hpp new file mode 100644 index 0000000..3602ff1 --- /dev/null +++ b/tests/utils/testutils/MemoryGuard/MemoryGuard.hpp @@ -0,0 +1,62 @@ +#pragma once +#if defined(__unix) || defined(__unix__) +#include +#include +#include + +extern "C" void add_to_guard(void*, size_t); +extern "C" void remove_from_guard(void*); + +namespace Testing { + struct MemoryNode { + MemoryNode *next; + + void *ptr; + size_t size; + }; + + class MemoryGuard { + public: + MemoryGuard(); + MemoryGuard(const MemoryGuard&) = delete; + MemoryGuard& operator=(const MemoryGuard&) = delete; + ~MemoryGuard(); + + void insert(void*, size_t); + void pop(void*); + [[nodiscard]] size_t total() const; + void setEnabled(bool enabled) { this->isEnabled = enabled; } + static MemoryGuard* instance(); + + [[nodiscard]] MemoryNode *node() const noexcept { return head; } + private: + MemoryNode *head = nullptr; + bool isEnabled = false; + }; +} // Testing + +#define ENABLE_MEMGUARD Testing::MemoryGuard::instance()->setEnabled(true); +#define DISABLE_MEMGUARD Testing::MemoryGuard::instance()->setEnabled(false); + +#define MEMGUARD_REPORT \ +__attribute__((destructor)) \ +void memguard_report() { \ + DISABLE_MEMGUARD \ + std::cerr.flush(); \ + std::cout.flush(); \ + Testing::MemoryGuard *g_guard = Testing::MemoryGuard::instance(); \ + Testing::MemoryNode *head = g_guard->node(); \ + if (head) { \ + while (head) { \ + std::cerr << "0x" << reinterpret_cast(head->ptr) << " " << \ + head->size << std::endl; \ + head = head->next; \ + } \ + std::cerr << "Total leaked memory: " << g_guard->total() << std::endl; \ + } \ +} +#else +#define ENABLE_MEMGUARD +#define DISABLE_MEMGUARD +#define MEMGUARD_REPORT +#endif diff --git a/tests/utils/testutils/MemoryGuard/memutils.c b/tests/utils/testutils/MemoryGuard/memutils.c new file mode 100644 index 0000000..a28f47c --- /dev/null +++ b/tests/utils/testutils/MemoryGuard/memutils.c @@ -0,0 +1,44 @@ +#include "memutils.h" + +#if defined(__unix) || defined(__unix__) +extern void add_to_guard(void*, size_t); +extern void remove_from_guard(void*); + +void init_hooks() { + if (!real_malloc) + real_malloc = dlsym(RTLD_NEXT, "malloc"); + if (!real_calloc) + real_calloc = dlsym(RTLD_NEXT, "calloc"); + if (!real_realloc) + real_realloc = dlsym(RTLD_NEXT, "realloc"); + if (!real_free) + real_free = dlsym(RTLD_NEXT, "free"); +} + +void* malloc(size_t size) { + if (!real_malloc) init_hooks(); + void *ptr = real_malloc(size); + add_to_guard(ptr, size); + return ptr; +} + +void* calloc(size_t nmem, size_t size) { + if (!real_calloc) init_hooks(); + void *ptr = real_calloc(nmem, size); + add_to_guard(ptr, nmem * size); + return ptr; +} + +void* realloc(void *ptr, size_t size) { + if (!real_realloc) init_hooks(); + ptr = real_realloc(ptr, size); + add_to_guard(ptr, size); + return ptr; +} + +void free(void *ptr) { + if (!real_free) init_hooks(); + remove_from_guard(ptr); + real_free(ptr); +} +#endif diff --git a/tests/utils/testutils/MemoryGuard/memutils.h b/tests/utils/testutils/MemoryGuard/memutils.h new file mode 100644 index 0000000..ada1343 --- /dev/null +++ b/tests/utils/testutils/MemoryGuard/memutils.h @@ -0,0 +1,19 @@ +#ifndef AXON_MEMUTILS_H +#define AXON_MEMUTILS_H +#if defined(__unix) || defined(__unix__) +#include +#include + +// Hooks to "real" functions + +void* (*real_malloc) (size_t) = NULL; +void* (*real_calloc) (size_t, size_t) = NULL; +void* (*real_realloc) (void*, size_t) = NULL; +void (*real_free) (void*) = NULL; + +void *malloc(size_t size); +void *calloc(size_t nmem, size_t size); +void *realloc(void *ptr, size_t size); +void free(void *ptr); +#endif +#endif \ No newline at end of file From 142fca169fa03196b8a189e5c598ecfebd7089eb Mon Sep 17 00:00:00 2001 From: KbrdDestroyer Date: Fri, 30 May 2025 14:00:45 +0300 Subject: [PATCH 05/47] Added performance checks --- libraries/networking/message/AxonMessage.hpp | 6 ++-- .../networking-core/BasicSynapse.hpp | 2 +- .../networking-core/BasicSynapse.ipp | 4 +-- tests/performance/perf_message_api.cpp | 22 ++++++++++++++ tests/performance/perf_synapse.cpp | 30 +++++++++++++++++++ .../testutils/MemoryGuard/MemoryGuard.cpp | 2 +- 6 files changed, 59 insertions(+), 7 deletions(-) create mode 100644 tests/performance/perf_message_api.cpp create mode 100644 tests/performance/perf_synapse.cpp diff --git a/libraries/networking/message/AxonMessage.hpp b/libraries/networking/message/AxonMessage.hpp index c784905..cfff75e 100644 --- a/libraries/networking/message/AxonMessage.hpp +++ b/libraries/networking/message/AxonMessage.hpp @@ -1,5 +1,7 @@ /* AxonMessage.hpp */ +// TODO: Code styling, remove all shit pls + #pragma once #include @@ -59,7 +61,7 @@ namespace Networking size64_t size = 0; uint16_t uniqueID = 0; uintptr_t offset = 0; - bool owning = true; + bool owning = true; // todo: `uint16_t _refcnt;` or shared_ptr around bytes array const char* bytes = nullptr; friend class AxonMessage; @@ -114,10 +116,8 @@ namespace Networking protected: static uint16_t generateUniqueID() { static uint16_t uniqueID = 0; - if (uniqueID == INT16_MAX - 1) uniqueID = 0; - return uniqueID++; } void decompressTag(TAG_T, uint8_t*, uint8_t*, uint16_t*); diff --git a/libraries/networking/networking-core/BasicSynapse.hpp b/libraries/networking/networking-core/BasicSynapse.hpp index dd34bbc..cdb4697 100644 --- a/libraries/networking/networking-core/BasicSynapse.hpp +++ b/libraries/networking/networking-core/BasicSynapse.hpp @@ -46,7 +46,7 @@ namespace Networking { virtual void update() {} virtual void onMessageReceived(const AxonMessage&, SOCKADDR_IN_T*) {}; - void processIncomingMessage(SerializedAxonMessage, SOCKADDR_IN_T*); + void processIncomingMessage(const SerializedAxonMessage&, SOCKADDR_IN_T*); protected: std::atomic isAlive = false; // TODO: move this from here ConnectionInfo connectionInfo; diff --git a/libraries/networking/networking-core/BasicSynapse.ipp b/libraries/networking/networking-core/BasicSynapse.ipp index 9751982..6925668 100644 --- a/libraries/networking/networking-core/BasicSynapse.ipp +++ b/libraries/networking/networking-core/BasicSynapse.ipp @@ -49,7 +49,7 @@ template Networking::BasicSynapse::~BasicSynapse() { isAlive = false; - finalize_udp(socketInfo.socket); + finalize(socketInfo); } #pragma endregion @@ -80,7 +80,7 @@ void Networking::BasicSynapse::sendTo(const SerializedAxonMessage& s } template -void Networking::BasicSynapse::processIncomingMessage(SerializedAxonMessage message, SOCKADDR_IN_T *host) { +void Networking::BasicSynapse::processIncomingMessage(const SerializedAxonMessage &message, SOCKADDR_IN_T *host) { onMessageReceived(AxonMessage(message), host); } diff --git a/tests/performance/perf_message_api.cpp b/tests/performance/perf_message_api.cpp new file mode 100644 index 0000000..f2d49a3 --- /dev/null +++ b/tests/performance/perf_message_api.cpp @@ -0,0 +1,22 @@ +#include +#include + +int main() { + ENABLE_MEMGUARD + + Networking::AxonMessage msg1(nullptr, 0); + Networking::AxonMessage msg2("Hello World", 12, 0, 1); + + Networking::SerializedAxonMessage serializedAxonMessage1 = msg1.getSerialized(); + Networking::SerializedAxonMessage serializedAxonMessage2(msg2); + + Networking::AxonMessage cpyMsg1(msg1); + Networking::AxonMessage cpyMsg2 = msg2; + + Networking::SerializedAxonMessage serializedAxonMessageCpy1(serializedAxonMessage1); + Networking::SerializedAxonMessage serializedAxonMessageCpy2 = serializedAxonMessage2; + + msg1.split(2); +} + +MEMGUARD_REPORT diff --git a/tests/performance/perf_synapse.cpp b/tests/performance/perf_synapse.cpp new file mode 100644 index 0000000..3c1190d --- /dev/null +++ b/tests/performance/perf_synapse.cpp @@ -0,0 +1,30 @@ +#include +#include +#include +#include + +int main() { + Networking::AsyncSynapse server(10432); + Networking::AsyncSynapse client({"localhost", 10432}); + server.start(); + client.start(); + + ENABLE_MEMGUARD + + for (uint8_t i = 0; i < 0; i++) + { + DISABLE_MEMGUARD + std::this_thread::sleep_for(std::chrono::milliseconds (100)); + std::stringstream sstream; + sstream << + "Sending message on " << i; + Networking::AxonMessage message_(const_cast(sstream.str().c_str()), sstream.str().length() + 1, 0, Networking::TAG_FLAGS::VALIDATE); + ENABLE_MEMGUARD + client.send(message_); + } + + client.kill(); + server.kill(); +} + +MEMGUARD_REPORT diff --git a/tests/utils/testutils/MemoryGuard/MemoryGuard.cpp b/tests/utils/testutils/MemoryGuard/MemoryGuard.cpp index 7100f4a..b9983e2 100644 --- a/tests/utils/testutils/MemoryGuard/MemoryGuard.cpp +++ b/tests/utils/testutils/MemoryGuard/MemoryGuard.cpp @@ -24,7 +24,7 @@ namespace Testing { while (head) { MemoryNode *dummy = head; head = head->next; - real_free(head); + real_free(dummy); } } From fd9550120e26d212b49ebc5876eb2abf4563ca16 Mon Sep 17 00:00:00 2001 From: KbrdDestroyer Date: Fri, 30 May 2025 17:38:47 +0300 Subject: [PATCH 06/47] Fix TCP multiplexing --- examples/basics/basic-synapse/client.cpp | 4 +- examples/basics/basic-synapse/server.cpp | 2 +- .../networking-core/BasicSynapse.hpp | 4 +- .../networking-core/BasicSynapse.ipp | 25 +++++----- .../networking/networking-core/Synapse.hpp | 2 +- .../networking/networking-core/Synapse.ipp | 6 +-- .../networking-core/SynapseEvents.hpp | 13 ++--- tests/gtest/test_synapse.cpp | 49 +++++++++++++++++++ 8 files changed, 77 insertions(+), 28 deletions(-) create mode 100644 tests/gtest/test_synapse.cpp diff --git a/examples/basics/basic-synapse/client.cpp b/examples/basics/basic-synapse/client.cpp index ab8060f..2a72178 100644 --- a/examples/basics/basic-synapse/client.cpp +++ b/examples/basics/basic-synapse/client.cpp @@ -36,10 +36,8 @@ int main() { Networking::ConnectionInfo connection = { "localhost", 10423 }; - Networking::AsyncSynapse clientConnection(connection); + Networking::Synapse clientConnection(connection); clientConnection.getEventManager().subscribe(onMessageReceived); - - clientConnection.start(); time_t startTimestamp = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); Networking::AxonMessage msg(nullptr, 0); diff --git a/examples/basics/basic-synapse/server.cpp b/examples/basics/basic-synapse/server.cpp index cb87b66..ce27ddd 100644 --- a/examples/basics/basic-synapse/server.cpp +++ b/examples/basics/basic-synapse/server.cpp @@ -31,7 +31,7 @@ void onMessageReceived(const Networking::SynapseMessageReceivedEvent& event) int main() { - Networking::AsyncSynapse serverConnection(10423); + Networking::Synapse serverConnection(10423); serverConnection.getEventManager().subscribe(onMessageReceived); std::cout << "Starting Synapse connection" << std::endl; diff --git a/libraries/networking/networking-core/BasicSynapse.hpp b/libraries/networking/networking-core/BasicSynapse.hpp index cdb4697..38bba88 100644 --- a/libraries/networking/networking-core/BasicSynapse.hpp +++ b/libraries/networking/networking-core/BasicSynapse.hpp @@ -44,9 +44,9 @@ namespace Networking { // This function should be instanced for each connection type virtual void listen() {} virtual void update() {} - virtual void onMessageReceived(const AxonMessage&, SOCKADDR_IN_T*) {}; + virtual void onMessageReceived(const AxonMessage&, const Socket&) {}; - void processIncomingMessage(const SerializedAxonMessage&, SOCKADDR_IN_T*); + void processIncomingMessage(const SerializedAxonMessage&, const Socket&); protected: std::atomic isAlive = false; // TODO: move this from here ConnectionInfo connectionInfo; diff --git a/libraries/networking/networking-core/BasicSynapse.ipp b/libraries/networking/networking-core/BasicSynapse.ipp index 6925668..eada880 100644 --- a/libraries/networking/networking-core/BasicSynapse.ipp +++ b/libraries/networking/networking-core/BasicSynapse.ipp @@ -80,8 +80,8 @@ void Networking::BasicSynapse::sendTo(const SerializedAxonMessage& s } template -void Networking::BasicSynapse::processIncomingMessage(const SerializedAxonMessage &message, SOCKADDR_IN_T *host) { - onMessageReceived(AxonMessage(message), host); +void Networking::BasicSynapse::processIncomingMessage(const SerializedAxonMessage &message, const Socket& from) { + onMessageReceived(AxonMessage(message), from); } #pragma region SERVER_FUNCTIONS @@ -89,8 +89,6 @@ void Networking::BasicSynapse::processIncomingMessage(const Serializ template<> inline void Networking::BasicSynapse::listen() { - SOCKADDR_IN_T host = {}; - fd_set master; FD_ZERO(&master); FD_SET(socketInfo.socket, &master); @@ -120,15 +118,18 @@ inline void Networking::BasicSynapse(socketInfo, buffer, 256); - - if (size < 0) { + Socket socket = { connectionSock, {} }; + const int32_t size = recv_message(socket, buffer, 256); + if (size > 0) + { + processIncomingMessage(SerializedAxonMessage(buffer, size), socket); + } + else if (size < 0) + { FD_CLR(connectionSock, &master); CLOSESOCKET(connectionSock); continue; } - - processIncomingMessage(SerializedAxonMessage(buffer, size), &socketInfo.conn); } } } @@ -145,7 +146,7 @@ inline void Networking::BasicSynapse(socketInfo, buffer, SYNAPSE_MESSAGE_SIZE_MAX); if (size > 0) { - processIncomingMessage(SerializedAxonMessage(buffer, size), &socketInfo.conn); + processIncomingMessage(SerializedAxonMessage(buffer, size), socketInfo); } update(); @@ -168,7 +169,7 @@ inline void Networking::BasicSynapse(buffer), 256, client); if (size > 0) { - processIncomingMessage(SerializedAxonMessage(buffer, size), &host); + processIncomingMessage(SerializedAxonMessage(buffer, size), socketInfo); } update(); @@ -184,7 +185,7 @@ inline void Networking::BasicSynapse (buffer), SYNAPSE_MESSAGE_SIZE_MAX, socketInfo.socket, &host); if (size > 0) { - processIncomingMessage(SerializedAxonMessage(buffer, size), &host); + processIncomingMessage(SerializedAxonMessage(buffer, size), socketInfo); } update(); diff --git a/libraries/networking/networking-core/Synapse.hpp b/libraries/networking/networking-core/Synapse.hpp index 253c96c..3f35c95 100644 --- a/libraries/networking/networking-core/Synapse.hpp +++ b/libraries/networking/networking-core/Synapse.hpp @@ -39,7 +39,7 @@ namespace Networking #pragma region INTERFACE void update() override; - void onMessageReceived(const AxonMessage&, SOCKADDR_IN_T*) override; + void onMessageReceived(const AxonMessage&, const Socket&) override; EventSystem::AxonEventManager& getEventManager() { return events; } void sendTo(AxonMessage&, const SOCKADDR_IN_T*) override; diff --git a/libraries/networking/networking-core/Synapse.ipp b/libraries/networking/networking-core/Synapse.ipp index a09ea96..e8dcd91 100644 --- a/libraries/networking/networking-core/Synapse.ipp +++ b/libraries/networking/networking-core/Synapse.ipp @@ -38,11 +38,11 @@ void Networking::Synapse::sendPooled(const AxonMessage& message, con } template -void Networking::Synapse::onMessageReceived(const AxonMessage& message, SOCKADDR_IN_T* from) +void Networking::Synapse::onMessageReceived(const AxonMessage& message, const Socket &from) { if (message.hasFlag(VALIDATE)) { - sendPooled(AxonMessage(message, 0), from); + sendPooled(AxonMessage(message, 0), &from.conn); } if (message.hasFlag(ACKNOWLEDGE) && !message.hasFlag(PARTIAL)) { @@ -71,7 +71,7 @@ void Networking::Synapse::onMessageReceived(const AxonMessage& messa #pragma endregion -#pragma region ASYNC_SYNAPS +#pragma region ASYNC_SYNAPSE template void Networking::AsyncSynapse::kill() diff --git a/libraries/networking/networking-core/SynapseEvents.hpp b/libraries/networking/networking-core/SynapseEvents.hpp index 9d899b8..2c0da4b 100644 --- a/libraries/networking/networking-core/SynapseEvents.hpp +++ b/libraries/networking/networking-core/SynapseEvents.hpp @@ -3,6 +3,8 @@ #include #include +struct Socket; + namespace Networking { /** * Event, that is generated when message is received from the remote. Can be used for message handling or output @@ -10,15 +12,14 @@ namespace Networking { class AXON_DECLSPEC SynapseMessageReceivedEvent final : public EventSystem::AxonEvent { public: - SynapseMessageReceivedEvent(const AxonMessage& message, SOCKADDR_IN_T* from) : AxonEvent(), message(message) - { - this->from = from; - } + SynapseMessageReceivedEvent(const AxonMessage& message, const Socket &from) : + AxonEvent(), message(message), from(from) + {} GETTER const AxonMessage& getMessage() const { return message; } - GETTER SOCKADDR_IN_T* getFrom() const { return from; } + GETTER const Socket& getFrom() const { return from; } private: const AxonMessage& message; - SOCKADDR_IN_T* from; + const Socket& from; }; } \ No newline at end of file diff --git a/tests/gtest/test_synapse.cpp b/tests/gtest/test_synapse.cpp new file mode 100644 index 0000000..1cfd119 --- /dev/null +++ b/tests/gtest/test_synapse.cpp @@ -0,0 +1,49 @@ +#include +#include + +bool hasVisited = false; + +void onMessageReceived(const Networking::SynapseMessageReceivedEvent& event) { + ASSERT_STREQ(static_cast(event.getMessage().getMessage()), "Hello World!"); + hasVisited = true; +} + + +TEST(TEST_SYNAPSE, TEST_SYNAPSE_COMMON_UDP) { + Networking::AsyncSynapse server(10435); + Networking::AsyncSynapse client({"localhost", 10435}); + + server.getEventManager().subscribe(onMessageReceived); + server.start(); + client.start(); + + Networking::AxonMessage msg("Hello World!", sizeof("Hello World!")); + client.send(msg); + + std::this_thread::sleep_for(std::chrono::seconds(1)); + ASSERT_TRUE(hasVisited); + + hasVisited = false; +} + +TEST(TEST_SYNAPSE, TEST_SYNAPSE_COMMON_TCP) { + Networking::AsyncSynapse server(10435); + Networking::AsyncSynapse client({"localhost", 10435}); + + server.getEventManager().subscribe(onMessageReceived); + server.start(); + client.start(); + Networking::AxonMessage msg("Hello World!", sizeof("Hello World!"), 2, 0); + + for (uint8_t i = 0; i < 3; i++) + client.send(msg); + + std::this_thread::sleep_for(std::chrono::seconds(5)); + ASSERT_TRUE(hasVisited); +} + +int main(int argc, char* argv[]) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} From f45c94f11553d1c214b0c240816b223face17947 Mon Sep 17 00:00:00 2001 From: KbrdDestroyer Date: Fri, 30 May 2025 17:45:45 +0300 Subject: [PATCH 07/47] Fix TCP multiplexing - checked on example --- examples/basics/basic-synapse/client.cpp | 4 +++- .../networking/networking-core/BasicSynapse.hpp | 4 ++-- .../networking/networking-core/BasicSynapse.ipp | 8 ++++---- libraries/networking/networking-core/Synapse.hpp | 4 ++-- libraries/networking/networking-core/Synapse.ipp | 12 +++++------- libraries/networking/utility/MessagePool.hpp | 3 ++- 6 files changed, 18 insertions(+), 17 deletions(-) diff --git a/examples/basics/basic-synapse/client.cpp b/examples/basics/basic-synapse/client.cpp index 2a72178..d429d48 100644 --- a/examples/basics/basic-synapse/client.cpp +++ b/examples/basics/basic-synapse/client.cpp @@ -36,8 +36,10 @@ int main() { Networking::ConnectionInfo connection = { "localhost", 10423 }; - Networking::Synapse clientConnection(connection); + Networking::AsyncSynapse clientConnection(connection); clientConnection.getEventManager().subscribe(onMessageReceived); + clientConnection.start(); + time_t startTimestamp = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); Networking::AxonMessage msg(nullptr, 0); diff --git a/libraries/networking/networking-core/BasicSynapse.hpp b/libraries/networking/networking-core/BasicSynapse.hpp index 38bba88..6e065b1 100644 --- a/libraries/networking/networking-core/BasicSynapse.hpp +++ b/libraries/networking/networking-core/BasicSynapse.hpp @@ -38,8 +38,8 @@ namespace Networking { virtual void start(); virtual void send(AxonMessage&); - virtual void sendTo(AxonMessage&, const SOCKADDR_IN_T*); - virtual void sendTo(const SerializedAxonMessage&, const SOCKADDR_IN_T*) const; + virtual void sendTo(AxonMessage&, const Socket&); + virtual void sendTo(const SerializedAxonMessage&, const Socket&) const; // This function should be instanced for each connection type virtual void listen() {} diff --git a/libraries/networking/networking-core/BasicSynapse.ipp b/libraries/networking/networking-core/BasicSynapse.ipp index eada880..9a0b998 100644 --- a/libraries/networking/networking-core/BasicSynapse.ipp +++ b/libraries/networking/networking-core/BasicSynapse.ipp @@ -64,19 +64,19 @@ void Networking::BasicSynapse::start() template void Networking::BasicSynapse::send(AxonMessage& message) { - sendTo(message, &socketInfo.conn); + sendTo(message, socketInfo); } template -void Networking::BasicSynapse::sendTo(AxonMessage& message, const SOCKADDR_IN_T* dest) +void Networking::BasicSynapse::sendTo(AxonMessage& message, const Socket& dest) { sendTo(message.getSerialized(), dest); } template -void Networking::BasicSynapse::sendTo(const SerializedAxonMessage& serialized, const SOCKADDR_IN_T* dest) const +void Networking::BasicSynapse::sendTo(const SerializedAxonMessage& serialized, const Socket& dest) const { - send_message({ socketInfo.socket, *dest }, serialized.getBits(), serialized.getSize()); + send_message(dest, serialized.getBits(), serialized.getSize()); } template diff --git a/libraries/networking/networking-core/Synapse.hpp b/libraries/networking/networking-core/Synapse.hpp index 3f35c95..cd84cae 100644 --- a/libraries/networking/networking-core/Synapse.hpp +++ b/libraries/networking/networking-core/Synapse.hpp @@ -42,8 +42,8 @@ namespace Networking void onMessageReceived(const AxonMessage&, const Socket&) override; EventSystem::AxonEventManager& getEventManager() { return events; } - void sendTo(AxonMessage&, const SOCKADDR_IN_T*) override; - void sendPooled(const AxonMessage&, const SOCKADDR_IN_T* = nullptr) const; + void sendTo(AxonMessage&, const Socket&) override; + void sendPooled(const AxonMessage&, const Socket &) const; #pragma endregion protected: EventSystem::AxonEventManager events; diff --git a/libraries/networking/networking-core/Synapse.ipp b/libraries/networking/networking-core/Synapse.ipp index e8dcd91..29e7363 100644 --- a/libraries/networking/networking-core/Synapse.ipp +++ b/libraries/networking/networking-core/Synapse.ipp @@ -11,11 +11,11 @@ void Networking::Synapse::update() { if (!pNode.get()) return; - this->sendTo(pNode->message, &pNode->destination); + this->sendTo(pNode->message, pNode->destination); } template -void Networking::Synapse::sendTo(AxonMessage &message, const SOCKADDR_IN_T *dest) { +void Networking::Synapse::sendTo(AxonMessage &message, const Socket &dest) { Networking::AxonMessage::UniqueAxonMessagePtr ptr = message.split(SYNAPSE_PAYLOAD_SIZE_MAX); if (ptr) { @@ -31,10 +31,8 @@ void Networking::Synapse::sendTo(AxonMessage &message, const SOCKADD } template -void Networking::Synapse::sendPooled(const AxonMessage& message, const SOCKADDR_IN_T* dest) const { - if (!dest) - dest = &this->socketInfo.conn; - pool->push( { message, *dest } ); +void Networking::Synapse::sendPooled(const AxonMessage& message, const Socket &dest) const { + pool->push( { message, dest } ); } template @@ -42,7 +40,7 @@ void Networking::Synapse::onMessageReceived(const AxonMessage& messa { if (message.hasFlag(VALIDATE)) { - sendPooled(AxonMessage(message, 0), &from.conn); + sendPooled(AxonMessage(message, 0), from); } if (message.hasFlag(ACKNOWLEDGE) && !message.hasFlag(PARTIAL)) { diff --git a/libraries/networking/utility/MessagePool.hpp b/libraries/networking/utility/MessagePool.hpp index e46cbf5..234f6b6 100644 --- a/libraries/networking/utility/MessagePool.hpp +++ b/libraries/networking/utility/MessagePool.hpp @@ -1,5 +1,6 @@ #pragma once #include +#include #include #include #include @@ -12,7 +13,7 @@ namespace Networking { struct AXON_DECLSPEC MessagePoolNode { AxonMessage message; - SOCKADDR_IN_T destination; + Socket destination; }; typedef std::shared_ptr MessagePoolNodePtr; From c07c42303f6d20dee86f617178803572f8530a81 Mon Sep 17 00:00:00 2001 From: Keyboard Destroyer Date: Sat, 31 May 2025 18:24:05 +0300 Subject: [PATCH 08/47] Fix message split algorythm, fix multiplexing issues --- examples/basics/basic-synapse/client.cpp | 5 ++++- libraries/networking/message/AxonMessage.cpp | 2 +- libraries/networking/networking-core/Synapse.ipp | 2 +- libraries/networking/utility/MessagePool.hpp | 5 ++--- tests/utils/testutils/MemoryGuard/MemoryGuard.hpp | 3 +++ 5 files changed, 11 insertions(+), 6 deletions(-) diff --git a/examples/basics/basic-synapse/client.cpp b/examples/basics/basic-synapse/client.cpp index d429d48..b7e12fb 100644 --- a/examples/basics/basic-synapse/client.cpp +++ b/examples/basics/basic-synapse/client.cpp @@ -55,7 +55,10 @@ int main() sstream << "Sending message on " << std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()) - startTimestamp; - Networking::AxonMessage message_(const_cast(sstream.str().c_str()), sstream.str().length() + 1, 0, Networking::TAG_FLAGS::VALIDATE); + + std::cout << "Sending: " << sstream.str() << std::endl; + + Networking::AxonMessage message_(const_cast(sstream.str().c_str()), sstream.str().length() + 2, 0, Networking::TAG_FLAGS::VALIDATE); clientConnection.send(message_); } diff --git a/libraries/networking/message/AxonMessage.cpp b/libraries/networking/message/AxonMessage.cpp index 14f931c..0ee9198 100644 --- a/libraries/networking/message/AxonMessage.cpp +++ b/libraries/networking/message/AxonMessage.cpp @@ -164,7 +164,7 @@ Networking::AxonMessage::UniqueAxonMessagePtr Networking::AxonMessage::split(con } void Networking::AxonMessage::append(const Networking::AxonMessage &other) { - if (!other.getMessage() || other.size == 0 || other.partID == partID + 1) + if (!other.getMessage() || other.size == 0 || other.partID != partID + 1) return; char* tempBuffer = new char[other.size + size]; diff --git a/libraries/networking/networking-core/Synapse.ipp b/libraries/networking/networking-core/Synapse.ipp index 29e7363..ce523b1 100644 --- a/libraries/networking/networking-core/Synapse.ipp +++ b/libraries/networking/networking-core/Synapse.ipp @@ -16,7 +16,7 @@ void Networking::Synapse::update() { template void Networking::Synapse::sendTo(AxonMessage &message, const Socket &dest) { - Networking::AxonMessage::UniqueAxonMessagePtr ptr = message.split(SYNAPSE_PAYLOAD_SIZE_MAX); + const AxonMessage::UniqueAxonMessagePtr ptr = message.split(SYNAPSE_PAYLOAD_SIZE_MAX); if (ptr) { sendPooled(*ptr.get(), dest); diff --git a/libraries/networking/utility/MessagePool.hpp b/libraries/networking/utility/MessagePool.hpp index 234f6b6..165cffa 100644 --- a/libraries/networking/utility/MessagePool.hpp +++ b/libraries/networking/utility/MessagePool.hpp @@ -36,7 +36,7 @@ namespace Networking { class MessageMapComparator { public: - bool operator() ( const AxonMessagePtr& l, const AxonMessagePtr& r ) { return l->getPartID() < r->getPartID(); } + bool operator() ( const AxonMessagePtr& l, const AxonMessagePtr& r ) const { return l->getPartID() < r->getPartID(); } }; typedef std::priority_queue, MessageMapComparator> MessageMapNode; public: @@ -48,7 +48,7 @@ namespace Networking { auto it = messagePool.find(message.ID()); if (it != messagePool.end()) { - if (message.getPartID() == it->second.top()->getPartID() + 1) + if (!it->second.empty() && message.getPartID() == it->second.top()->getPartID() + 1) { it->second.top()->append(message); return it->second.top(); @@ -80,7 +80,6 @@ namespace Networking { bool contains(uint16_t id) { return messagePool.find(id) != messagePool.end(); } - protected: private: std::map messagePool; }; diff --git a/tests/utils/testutils/MemoryGuard/MemoryGuard.hpp b/tests/utils/testutils/MemoryGuard/MemoryGuard.hpp index 3602ff1..7d8d61e 100644 --- a/tests/utils/testutils/MemoryGuard/MemoryGuard.hpp +++ b/tests/utils/testutils/MemoryGuard/MemoryGuard.hpp @@ -56,6 +56,9 @@ void memguard_report() { } \ } #else +#pragma message( __FILE__ " MemoryGuard is not supported on current platform" ) +#pragma message( "MemoryGuard is disabled" ) + #define ENABLE_MEMGUARD #define DISABLE_MEMGUARD #define MEMGUARD_REPORT From 5b462eda97610c412d6e4e2c0020c38bbe01d66d Mon Sep 17 00:00:00 2001 From: Keyboard Destroyer Date: Sun, 1 Jun 2025 10:35:26 +0300 Subject: [PATCH 09/47] Formatted examples folder sources --- examples/basics/basic-synapse/client.cpp | 15 ++++++++------- examples/basics/basic-synapse/server.cpp | 6 +++--- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/examples/basics/basic-synapse/client.cpp b/examples/basics/basic-synapse/client.cpp index b7e12fb..e96a63e 100644 --- a/examples/basics/basic-synapse/client.cpp +++ b/examples/basics/basic-synapse/client.cpp @@ -1,8 +1,9 @@ /* -* This example shows basic connection, using Axon internal tools -* Synapse provides connection between two points +* This example shows basic client connection, using Axon internal tools. +* Synapse provides connection between two points, this one is created in client mode. * -* This file defined basic client logic, with AxonMessage forming and sending with Synapse tool +* This file defined basic client logic. It creates Message package and sends it to server. Also, it is capable of +* server messages handling, displaying response packages. */ #include @@ -50,15 +51,15 @@ int main() { std::this_thread::sleep_for(std::chrono::seconds(1)); - std::stringstream sstream; + std::stringstream stream; - sstream << + stream << "Sending message on " << std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()) - startTimestamp; - std::cout << "Sending: " << sstream.str() << std::endl; + std::cout << "Sending: " << stream.str() << std::endl; - Networking::AxonMessage message_(const_cast(sstream.str().c_str()), sstream.str().length() + 2, 0, Networking::TAG_FLAGS::VALIDATE); + Networking::AxonMessage message_(const_cast(stream.str().c_str()), stream.str().length() + 2, 0, Networking::TAG_FLAGS::VALIDATE); clientConnection.send(message_); } diff --git a/examples/basics/basic-synapse/server.cpp b/examples/basics/basic-synapse/server.cpp index ce27ddd..7772919 100644 --- a/examples/basics/basic-synapse/server.cpp +++ b/examples/basics/basic-synapse/server.cpp @@ -1,8 +1,8 @@ /* -* This example shows basic connection, using Axon internal tools -* Synapse provides connection between two points +* This example shows basic server, using Axon internal tools. +* Synapse provides connection between two points, this one is created in server mode. * -* This file defines basic server logic, with message handling using Synapse event system +* This file shows basic server logic and message handling using asynchronous Synapse with event system. */ #include From 35ed5d9e69b6614fd81fa8e7958c674f1437e677 Mon Sep 17 00:00:00 2001 From: Keyboard Destroyer Date: Sun, 1 Jun 2025 10:46:52 +0300 Subject: [PATCH 10/47] Added comment section in CONTRIBUTING.md --- CONTRIBUTING.md | 5 +++++ examples/README.md | 2 ++ include/common_macro.h | 4 ++++ 3 files changed, 11 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fa15cc5..6bdf869 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -143,6 +143,11 @@ namespace MyNamespace { As said above, avoid raw memory allocation in C++ code. Use smart pointers instead. Functions like `malloc`, `calloc`, and `free` are forbidden in C++ code. +### Code documenting + +Comments in code are preferred, but not always necessary. There are some basic rules of proper code documentation, +which can be found [here](https://developer.lsst.io/cpp/api-docs.html). + --- If you find code that doesn’t follow these guidelines, [open an issue](https://github.com/kbrddestroyer/AxonEngine/issues/new) with the `refactoring` label. diff --git a/examples/README.md b/examples/README.md index e69de29..65afe60 100644 --- a/examples/README.md +++ b/examples/README.md @@ -0,0 +1,2 @@ +# Examples + diff --git a/include/common_macro.h b/include/common_macro.h index 58d0259..51e8f91 100644 --- a/include/common_macro.h +++ b/include/common_macro.h @@ -1,3 +1,7 @@ +/** + * + */ + #ifndef AXONENGINE_COMMON_MACRO_H #define AXONENGINE_COMMON_MACRO_H From 98ba9ccc82ac331e2106391ee96c0edc2beda950 Mon Sep 17 00:00:00 2001 From: Keyboard Destroyer Date: Sun, 1 Jun 2025 11:05:04 +0300 Subject: [PATCH 11/47] Commented include/ folder --- include/common_macro.h | 2 +- include/custom_utility.h | 11 +++++++++-- include/netconfig.h | 2 +- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/include/common_macro.h b/include/common_macro.h index 51e8f91..6caad64 100644 --- a/include/common_macro.h +++ b/include/common_macro.h @@ -1,5 +1,5 @@ /** - * + * Defines some useful macro, mostly for C code and backends. */ #ifndef AXONENGINE_COMMON_MACRO_H diff --git a/include/custom_utility.h b/include/custom_utility.h index a62b49c..3933524 100644 --- a/include/custom_utility.h +++ b/include/custom_utility.h @@ -1,3 +1,7 @@ +/** + * Contains utility types, functions, etc. + */ + #ifndef CUSTOM_UTILITY_H #define CUSTOM_UTILITY_H @@ -6,8 +10,11 @@ #else #include #endif -// Define alias for uint64_t to be used instead of size_t -// as size_t may have different size on different machines (i.e. x86 vs x64) + +/** +* Define alias for uint64_t to be used instead of size_t +* as size_t may have different size on different machines (i.e. x86 vs x64) +*/ typedef uint64_t size64_t; #endif //CUSTOM_UTILITY_H diff --git a/include/netconfig.h b/include/netconfig.h index c407114..49ec335 100644 --- a/include/netconfig.h +++ b/include/netconfig.h @@ -1,4 +1,4 @@ #pragma once #define SYNAPSE_PAYLOAD_SIZE_MAX 16 -#define SYNAPSE_MESSAGE_SIZE_MAX SYNAPSE_PAYLOAD_SIZE_MAX + 16 + 64 +#define SYNAPSE_MESSAGE_SIZE_MAX (SYNAPSE_PAYLOAD_SIZE_MAX + 16 + 64) From 5591021602e5a3be991619e406b5325087dbbe81 Mon Sep 17 00:00:00 2001 From: Keyboard Destroyer Date: Sun, 1 Jun 2025 11:34:27 +0300 Subject: [PATCH 12/47] Slightly changed backend.hpp definitions --- libraries/backends/backend.cpp | 4 ++-- libraries/backends/backend.hpp | 25 +++++++++++-------------- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/libraries/backends/backend.cpp b/libraries/backends/backend.cpp index be45f92..f56ca54 100644 --- a/libraries/backends/backend.cpp +++ b/libraries/backends/backend.cpp @@ -30,12 +30,12 @@ template <> uint8_t initialize_server(Socket& socket, uint32_t port) return create_udp_server(&socket.conn, &socket.socket, port); } -template <> uint8_t initialize_client(Socket& socket, const char* hostname, uint32_t port) +template <> uint8_t initialize_client(Socket& socket, const char* hostname, const uint32_t port) { return connect_tcp_client(&socket.conn, &socket.socket, hostname, port); } -template <> uint8_t initialize_client(Socket& socket, const char* hostname, uint32_t port) +template <> uint8_t initialize_client(Socket& socket, const char* hostname, const uint32_t port) { return connect_udp_client(&socket.conn, &socket.socket, hostname, port); } diff --git a/libraries/backends/backend.hpp b/libraries/backends/backend.hpp index d8bc5c5..0a3d5ec 100644 --- a/libraries/backends/backend.hpp +++ b/libraries/backends/backend.hpp @@ -1,27 +1,22 @@ +/** + * backend library. + * Contains functions for protocol-independent socket functions usage. Works with Berkeley sockets. + */ + #pragma once #ifdef __cplusplus extern "C" { #endif -#if defined(USE_BERKELEY) -#include "berkeley/basic_networking.h" -#else - /* DEFAULT */ -#endif - #include "berkeley/basic_networking.h" #ifdef __cplusplus } #endif -template int32_t send_message(const Socket& socket, const void* message, size_t size); - -template int32_t recv_message(Socket& socket, void* buffer, size_t size_allocated); - -template uint8_t initialize_server(Socket& socket, uint32_t port); - -template uint8_t initialize_client(Socket& socket, const char* hostname, uint32_t port); - +template int32_t send_message(const Socket& socket, const void* message, size_t size) = delete; +template int32_t recv_message(Socket& socket, void* buffer, size_t size_allocated) = delete; +template uint8_t initialize_server(Socket& socket, uint32_t port) = delete; +template uint8_t initialize_client(Socket& socket, const char* hostname, uint32_t port) = delete; template void finalize(Socket& socket); template <> int32_t send_message(const Socket&, const void*, size_t); @@ -33,6 +28,8 @@ template <> int32_t recv_message(Socket&, void*, size_t); template <> uint8_t initialize_server(Socket&, uint32_t); template <> uint8_t initialize_server(Socket&, uint32_t); +template <> uint8_t initialize_client(Socket&, const char*, uint32_t); +template <> uint8_t initialize_client(Socket&, const char*, uint32_t); template <> void finalize(Socket &); template <> void finalize(Socket &); From 781b84535d45100bf06d8abef6ec189dc7299248 Mon Sep 17 00:00:00 2001 From: Keyboard Destroyer Date: Sun, 1 Jun 2025 11:48:51 +0300 Subject: [PATCH 13/47] Commented and documented tcp --- include/custom_utility.h | 7 ++ libraries/backends/backend.hpp | 1 + .../backends/berkeley/basic_networking.h | 8 +-- libraries/backends/berkeley/master_include.h | 16 ++++- .../backends/berkeley/tcp/tcp_connection.c | 64 +++++++++++++++---- .../backends/berkeley/tcp/tcp_connection.h | 45 +------------ 6 files changed, 75 insertions(+), 66 deletions(-) diff --git a/include/custom_utility.h b/include/custom_utility.h index 3933524..74abb28 100644 --- a/include/custom_utility.h +++ b/include/custom_utility.h @@ -11,10 +11,17 @@ #include #endif +#include "common_macro.h" + /** * Define alias for uint64_t to be used instead of size_t * as size_t may have different size on different machines (i.e. x86 vs x64) */ typedef uint64_t size64_t; +struct Socket +{ + SOCKET_T socket; + SOCKADDR_IN_T conn; +}; #endif //CUSTOM_UTILITY_H diff --git a/libraries/backends/backend.hpp b/libraries/backends/backend.hpp index 0a3d5ec..99fc06e 100644 --- a/libraries/backends/backend.hpp +++ b/libraries/backends/backend.hpp @@ -9,6 +9,7 @@ extern "C" { #endif #include "berkeley/basic_networking.h" +#include "custom_utility.h" #ifdef __cplusplus } #endif diff --git a/libraries/backends/berkeley/basic_networking.h b/libraries/backends/berkeley/basic_networking.h index dc61d0d..c101f74 100644 --- a/libraries/backends/berkeley/basic_networking.h +++ b/libraries/backends/berkeley/basic_networking.h @@ -1,4 +1,4 @@ -/* +/** * Can be used as template for any other backends * * Defines some low-level socket logic. Direct usage is not recommended @@ -12,12 +12,6 @@ #include "udp/udp_connection.h" #include "tcp/tcp_connection.h" -struct Socket -{ - SOCKET_T socket; - SOCKADDR_IN_T conn; -}; - #endif /* basic_networking.h */ diff --git a/libraries/backends/berkeley/master_include.h b/libraries/backends/berkeley/master_include.h index 04e3815..6d6885e 100644 --- a/libraries/backends/berkeley/master_include.h +++ b/libraries/backends/berkeley/master_include.h @@ -1,11 +1,21 @@ +/** + * Header, that aggregates some includes for every other berkeley backend source file + */ + #ifndef MASTER_INCLUDE_H #define MASTER_INCLUDE_H +#ifdef __cplusplus +extern "C" { +#endif + #include #include - -/* common */ - #include #include + +#ifdef __cplusplus +} +#endif + #endif diff --git a/libraries/backends/berkeley/tcp/tcp_connection.c b/libraries/backends/berkeley/tcp/tcp_connection.c index a8976c1..38cb6e9 100644 --- a/libraries/backends/berkeley/tcp/tcp_connection.c +++ b/libraries/backends/berkeley/tcp/tcp_connection.c @@ -1,6 +1,27 @@ #include "tcp_connection.h" #include +/** + * Accept client connection to server + * @param server server socket + * @param [out] c_addr client information + * @return + */ +SOCKET_T accept_incoming(const SOCKET_T server, const SOCKADDR_IN_T *c_addr) +{ + SOCKLEN_T addr_s = sizeof(*c_addr); + return accept(server, (SOCKADDR_T*) c_addr, &addr_s); +} + +/** +* Connects to the remote host via TCP. Uses `getaddrinfo`. +* @param [out] server server SOCKADDR_IN_T structure +* @param client bound client socket +* @param hostname ip/hostname of a target node +* @param port port of a target node +* @returns 0 +* @returns ERR_CODE (defined in basic_networking.h) +*/ uint8_t connect_tcp_client(SOCKADDR_IN_T* server, SOCKET_T* client, const char* hostname, uint32_t port) { SOCKET_HEAD_INIT @@ -8,9 +29,7 @@ uint8_t connect_tcp_client(SOCKADDR_IN_T* server, SOCKET_T* client, const char* if (!CHECK_VALID(*client = socket(AF_INET, SOCK_STREAM, 0))) return ERR_INVALID; - ADDRINFO_T hints; - - memset(&hints, 0, sizeof(hints)); + ADDRINFO_T hints = {0}; hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; @@ -39,7 +58,14 @@ uint8_t connect_tcp_client(SOCKADDR_IN_T* server, SOCKET_T* client, const char* return SUCCESS; } - +/** +* Initializes server socket with TCP protocol. +* @param [out] server server information (SOCKADDR_IN_T structure) +* @param server_socket bound server socket +* @param port port to create server onto +* @returns 0 +* @returns ERR_CODE (defined in basic_networking.h) +*/ uint8_t create_tcp_server(SOCKADDR_IN_T* server, SOCKET_T* server_socket, uint32_t port) { SOCKET_HEAD_INIT @@ -64,23 +90,35 @@ uint8_t create_tcp_server(SOCKADDR_IN_T* server, SOCKET_T* server_socket, uint32 return SUCCESS; } -int32_t send_tcp_message(const void* message, size_t size, SOCKET_T from) +/** +* Sends data over UDP +* @param message data to send, sequence of bytes +* @param size size of message, bytes. Most of the time can be strlen(message), but we cannot be sure in case, when message is serialized data +* @param from source socket +* @returns send() function result +*/ +int32_t send_tcp_message(const void* message, const size_t size, const SOCKET_T from) { return send(from, message, size, 0); } -int32_t recv_tcp_message(void* const message, size_t max_size, SOCKET_T c_sock) +/** +* Handles message receiving over UDP +* @param message data buffer, must be either a static array or pre-allocated +* @param max_size max size of bytes that can be written in buffer +* @param c_sock client socket to receive message from +* @returns c_sock result +*/ +int32_t recv_tcp_message(void* const message, const size_t max_size, const SOCKET_T c_sock) { return recv(c_sock, message, max_size, 0); } -SOCKET_T accept_incoming(SOCKET_T server, SOCKADDR_IN_T* c_addr) -{ - SOCKLEN_T addr_s = sizeof(*c_addr); - return accept(server, (SOCKADDR_T*) c_addr, &addr_s); -} - -void finalize_tcp(SOCKET_T socket) +/** +* Closes socket, on Windows machines also cleanups WSA +* @param socket socket to close +*/ +void finalize_tcp(const SOCKET_T socket) { CLOSESOCKET(socket); #if defined(WIN32) diff --git a/libraries/backends/berkeley/tcp/tcp_connection.h b/libraries/backends/berkeley/tcp/tcp_connection.h index b356127..28bc489 100644 --- a/libraries/backends/berkeley/tcp/tcp_connection.h +++ b/libraries/backends/berkeley/tcp/tcp_connection.h @@ -5,53 +5,12 @@ #include #pragma region TCP_CONNECTION - -/** -* Connects to the remote host via TCP. Uses getaddrinfo. -* @param server -* @param client -* @param char* hostname -* @param port -* @return 0 or ERR_CODE (defined in basic_networking.h) -*/ -uint8_t connect_tcp_client(SOCKADDR_IN_T*, SOCKET_T*, const char*, uint32_t); - -/** -* Initializes server socket with TCP protocol. -* @param server -* @param server_socket -* @param port -* @returns 0 -* @returns ERR_CODE (defined in basic_networking.h) -*/ +uint8_t connect_tcp_client(SOCKADDR_IN_T *, SOCKET_T *, const char *, uint32_t); uint8_t create_tcp_server(SOCKADDR_IN_T*, SOCKET_T*, uint32_t); - -/** -* Sends data over UDP -* @param char* message - data to send, sequence of bytes -* @param size - size of message, bytes. Most of the time can be strlen(message), but we cannot be sure in case, when message is serialized data -* @param from - source -* @param to - destination -* @returns sendto result -*/ int32_t send_tcp_message(const void*, size_t, SOCKET_T); - -/** -* Handles message receiving over UDP -* @param buffer - data buffer -* @param max_size - max size of bytes that can be written in buffer -* @returns recvfrom result -*/ -int32_t recv_tcp_message(void* const, size_t, SOCKET_T); - +int32_t recv_tcp_message(void*, size_t, SOCKET_T); SOCKET_T accept_incoming(SOCKET_T, SOCKADDR_IN_T*); - -/** -* Closes socket -* @param socket -*/ void finalize_tcp(SOCKET_T); - #pragma endregion #endif From 0633d810a0fea9a1b5cfbbee8a4975207b1e3039 Mon Sep 17 00:00:00 2001 From: Keyboard Destroyer Date: Sun, 1 Jun 2025 11:53:08 +0300 Subject: [PATCH 14/47] Commented and formatted udp backend file --- .../backends/berkeley/tcp/tcp_connection.c | 4 +- .../backends/berkeley/udp/udp_connection.c | 46 ++++++++++++++++--- .../backends/berkeley/udp/udp_connection.h | 41 ----------------- 3 files changed, 42 insertions(+), 49 deletions(-) diff --git a/libraries/backends/berkeley/tcp/tcp_connection.c b/libraries/backends/berkeley/tcp/tcp_connection.c index 38cb6e9..eeaa98f 100644 --- a/libraries/backends/berkeley/tcp/tcp_connection.c +++ b/libraries/backends/berkeley/tcp/tcp_connection.c @@ -91,7 +91,7 @@ uint8_t create_tcp_server(SOCKADDR_IN_T* server, SOCKET_T* server_socket, uint32 } /** -* Sends data over UDP +* Sends data over TCP * @param message data to send, sequence of bytes * @param size size of message, bytes. Most of the time can be strlen(message), but we cannot be sure in case, when message is serialized data * @param from source socket @@ -103,7 +103,7 @@ int32_t send_tcp_message(const void* message, const size_t size, const SOCKET_T } /** -* Handles message receiving over UDP +* Handles message receiving over TCP * @param message data buffer, must be either a static array or pre-allocated * @param max_size max size of bytes that can be written in buffer * @param c_sock client socket to receive message from diff --git a/libraries/backends/berkeley/udp/udp_connection.c b/libraries/backends/berkeley/udp/udp_connection.c index 9d7b120..80ff997 100644 --- a/libraries/backends/berkeley/udp/udp_connection.c +++ b/libraries/backends/berkeley/udp/udp_connection.c @@ -5,6 +5,15 @@ #pragma region UDP_UTILS +/** +* Connects to the remote host via UDP. Uses `getaddrinfo`. +* @param [out] server server info (SOCKADDR_IN_T structure) +* @param client client socket +* @param hostname ip/hostname of a node to connect to +* @param port port of a node to connect to +* @returns 0 +* @returns ERR_CODE (defined in basic_networking.h) +*/ uint8_t connect_udp_client(SOCKADDR_IN_T* server, SOCKET_T* client, const char* hostname, uint32_t port) { SOCKET_HEAD_INIT @@ -12,9 +21,7 @@ uint8_t connect_udp_client(SOCKADDR_IN_T* server, SOCKET_T* client, const char* if (!CHECK_VALID(*client = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))) return ERR_INVALID; - ADDRINFO_T hints; - - memset(&hints, 0, sizeof(hints)); + ADDRINFO_T hints = {0}; hints.ai_family = AF_INET; hints.ai_socktype = SOCK_DGRAM; @@ -38,7 +45,14 @@ uint8_t connect_udp_client(SOCKADDR_IN_T* server, SOCKET_T* client, const char* return SUCCESS; } - +/** +* Initializes server socket with UDP protocol. +* @param [out] server server info (SOCKADDR_IN_T structure) +* @param [out] server_socket server socket that will be initialized +* @param port port to create server onto +* @returns 0 +* @returns ERR_CODE (defined in basic_networking.h) +*/ uint8_t create_udp_server(SOCKADDR_IN_T* server, SOCKET_T* server_socket, uint32_t port) { SOCKET_HEAD_INIT @@ -58,17 +72,37 @@ uint8_t create_udp_server(SOCKADDR_IN_T* server, SOCKET_T* server_socket, uint32 return SUCCESS; } +/** +* Sends data over UDP +* @param message data to send, sequence of bytes +* @param size size of message, bytes. Most of the time can be strlen(message), but we cannot be sure in case, when message is serialized data +* @param from source +* @param to destination +* @return sendto function result +*/ int32_t send_udp_message(const void* message, const size_t size, const SOCKET_T from, const SOCKADDR_IN_T* to) { return sendto(from, message, size, 0, (SOCKADDR_T*)to, sizeof(*to)); } +/** +* Handles message receiving over UDP +* @param message data buffer +* @param max_size max size of bytes that can be written in buffer +* @param to destination node +* @param from client information +* @return recvfrom function result +*/ int32_t recv_udp_message(void* const message, size_t max_size, SOCKET_T to, SOCKADDR_IN_T* from) { - SOCKLEN_T len = (SOCKLEN_T) sizeof(*from); - return recvfrom(to, message, max_size, 0, (SOCKADDR_T*)from, &len); + SOCKLEN_T len = sizeof(*from); + return recvfrom(to, message, max_size, 0, (SOCKADDR_T *) from, &len); } +/** +* Closes socket +* @param socket +*/ void finalize_udp(SOCKET_T socket) { CLOSESOCKET(socket); diff --git a/libraries/backends/berkeley/udp/udp_connection.h b/libraries/backends/berkeley/udp/udp_connection.h index ec00928..cbccf4c 100644 --- a/libraries/backends/berkeley/udp/udp_connection.h +++ b/libraries/backends/berkeley/udp/udp_connection.h @@ -6,55 +6,14 @@ #pragma region UDP_UTILS #pragma region CLIENT_UTILS - -/** -* Connects to the remote host via UDP. Uses getaddrinfo. -* @param server -* @param client -* @param hostname -* @param port -* @return 0 or ERR_CODE (defined in basic_networking.h) -*/ uint8_t connect_udp_client(SOCKADDR_IN_T*, SOCKET_T*, const char*, uint32_t); - #pragma endregion /* CLIENT UTILITY FUNCTIONS */ #pragma region SERVER_UTILS - -/** -* Initializes server socket with UDP protocol. -* @param server -* @param server_socket -* @param port -* @returns 0 -* @returns ERR_CODE (defined in basic_networking.h) -*/ uint8_t create_udp_server(SOCKADDR_IN_T*, SOCKET_T*, uint32_t); - #pragma endregion /* SERVER UTILITY FUNCTIONS */ - -/** -* Sends data over UDP -* @param message - data to send, sequence of bytes -* @param size - size of message, bytes. Most of the time can be strlen(message), but we cannot be sure in case, when message is serialized data -* @param from - source -* @param to - destination -* @return sendto result -*/ int32_t send_udp_message(const void*, size_t, SOCKET_T, const SOCKADDR_IN_T*); - -/** -* Handles message receiving over UDP -* @param buffer - data buffer -* @param max_size - max size of bytes that can be written in buffer -* @return recvfrom result -*/ int32_t recv_udp_message(void*, size_t, SOCKET_T, SOCKADDR_IN_T*); - -/** -* Closes socket -* @param socket -*/ void finalize_udp(SOCKET_T); #pragma endregion /* UDP UTILS */ From a800ef12a0e7ea1a9819e180e9ca159a44bd10a0 Mon Sep 17 00:00:00 2001 From: Keyboard Destroyer Date: Sun, 1 Jun 2025 14:15:22 +0300 Subject: [PATCH 15/47] Removed pragma region from UDP file --- libraries/backends/berkeley/udp/udp_connection.h | 7 ------- 1 file changed, 7 deletions(-) diff --git a/libraries/backends/berkeley/udp/udp_connection.h b/libraries/backends/berkeley/udp/udp_connection.h index cbccf4c..3a9dafc 100644 --- a/libraries/backends/berkeley/udp/udp_connection.h +++ b/libraries/backends/berkeley/udp/udp_connection.h @@ -4,17 +4,10 @@ #include #include -#pragma region UDP_UTILS -#pragma region CLIENT_UTILS uint8_t connect_udp_client(SOCKADDR_IN_T*, SOCKET_T*, const char*, uint32_t); -#pragma endregion /* CLIENT UTILITY FUNCTIONS */ - -#pragma region SERVER_UTILS uint8_t create_udp_server(SOCKADDR_IN_T*, SOCKET_T*, uint32_t); -#pragma endregion /* SERVER UTILITY FUNCTIONS */ int32_t send_udp_message(const void*, size_t, SOCKET_T, const SOCKADDR_IN_T*); int32_t recv_udp_message(void*, size_t, SOCKET_T, SOCKADDR_IN_T*); void finalize_udp(SOCKET_T); -#pragma endregion /* UDP UTILS */ #endif From 7e825ee0d5d367b8732c8b5a2ebf8d886e327483 Mon Sep 17 00:00:00 2001 From: Keyboard Destroyer Date: Sun, 1 Jun 2025 15:56:39 +0300 Subject: [PATCH 16/47] EventSystem refactored --- libraries/events/AxonEvent.cpp | 2 +- libraries/events/AxonEvent.hpp | 32 ++++++++++++++++++++++---------- libraries/events/AxonEvent.ipp | 4 ++-- 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/libraries/events/AxonEvent.cpp b/libraries/events/AxonEvent.cpp index 3e3eeb7..145067f 100644 --- a/libraries/events/AxonEvent.cpp +++ b/libraries/events/AxonEvent.cpp @@ -24,6 +24,6 @@ void EventSystem::AxonEventManager::invoke(AxonEvent* event) EventSystem::GlobalEventManager& EventSystem::GlobalEventManager::Instance() { - static EventSystem::GlobalEventManager instance; + static GlobalEventManager instance; return instance; } diff --git a/libraries/events/AxonEvent.hpp b/libraries/events/AxonEvent.hpp index 18c109c..424f45f 100644 --- a/libraries/events/AxonEvent.hpp +++ b/libraries/events/AxonEvent.hpp @@ -3,16 +3,29 @@ #include #include #include -#include namespace EventSystem { + /** + * Base class for any AxonEvent. Provides convenient interface (or will do some day). + */ class AxonEvent { public: virtual ~AxonEvent() = default; - }; + }; + + /** + * EventManager class is capable of dispatching triggered events.\n + * Usage: + * EventManager could be created literally anywhere. + * Callback method can be attached with subscribe() method. It will be dispatched when + * invoke() message is called. + * + * @note see GlobalEventManager + * @note see client-server example + */ class AxonEventManager { public: @@ -21,23 +34,22 @@ namespace EventSystem template void subscribe(std::function); - template - void subscribe(void (C::* method)(const T&), C* instance); + void subscribe(void (C::* callback)(const T&), C *instance); - void invoke(AxonEvent*); + void invoke(AxonEvent *); private: std::unordered_map>> subscribers; - - friend class GlobalEventManager; }; - class GlobalEventManager : public AxonEventManager + /** + * GlobalEventManager cannot be constructed, only accessed via Instance() method + */ + class GlobalEventManager final : public AxonEventManager { - private: GlobalEventManager() = default; public: - static GlobalEventManager& Instance(); + static GlobalEventManager& Instance() noexcept; }; } diff --git a/libraries/events/AxonEvent.ipp b/libraries/events/AxonEvent.ipp index 621e263..c0e0bf2 100644 --- a/libraries/events/AxonEvent.ipp +++ b/libraries/events/AxonEvent.ipp @@ -1,7 +1,7 @@ #pragma once template -inline void EventSystem::AxonEventManager::subscribe(std::function callback) +void EventSystem::AxonEventManager::subscribe(std::function callback) { std::type_index type = std::type_index(typeid(T)); @@ -16,7 +16,7 @@ inline void EventSystem::AxonEventManager::subscribe(std::function -inline void EventSystem::AxonEventManager::subscribe(void(C::* callback)(const T&), C* instance) +void EventSystem::AxonEventManager::subscribe(void(C::* callback)(const T&), C* instance) { std::type_index type = std::type_index(typeid(T)); From 3fcdffb369c23fa711122ade32e00c0622782f52 Mon Sep 17 00:00:00 2001 From: Keyboard Destroyer Date: Sun, 1 Jun 2025 16:15:22 +0300 Subject: [PATCH 17/47] Commented on AxonMessage --- libraries/backends/CMakeLists.txt | 2 +- libraries/events/CMakeLists.txt | 2 +- libraries/networking/CMakeLists.txt | 2 +- .../networking/message/AxonBinaryStream.cpp | 4 +- .../networking/message/AxonBinaryStream.hpp | 4 +- libraries/networking/message/AxonMessage.cpp | 18 +++--- libraries/networking/message/AxonMessage.hpp | 57 ++++++++++++------- 7 files changed, 51 insertions(+), 38 deletions(-) diff --git a/libraries/backends/CMakeLists.txt b/libraries/backends/CMakeLists.txt index 495936a..119ac20 100644 --- a/libraries/backends/CMakeLists.txt +++ b/libraries/backends/CMakeLists.txt @@ -1,4 +1,4 @@ -project ("AxonEngine.libraries") +project ("AxonEngine.libraries.backends") file(GLOB_RECURSE SOURCES "*.c" "*.h" "*.cpp" "*.hpp") add_library(backends STATIC ${SOURCES}) diff --git a/libraries/events/CMakeLists.txt b/libraries/events/CMakeLists.txt index c9c055b..fa4da64 100644 --- a/libraries/events/CMakeLists.txt +++ b/libraries/events/CMakeLists.txt @@ -1,4 +1,4 @@ -project ("AxonEngine.libraries") +project ("AxonEngine.libraries.events") file(GLOB_RECURSE SOURCES "*.c" "*.h" "*.cpp" "*.hpp" "*.ipp") add_library(events STATIC ${SOURCES}) diff --git a/libraries/networking/CMakeLists.txt b/libraries/networking/CMakeLists.txt index 6d715e5..868d64d 100644 --- a/libraries/networking/CMakeLists.txt +++ b/libraries/networking/CMakeLists.txt @@ -1,4 +1,4 @@ -project ("AxonEngine.libraries") +project ("AxonEngine.libraries.networking") file(GLOB_RECURSE SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.c" diff --git a/libraries/networking/message/AxonBinaryStream.cpp b/libraries/networking/message/AxonBinaryStream.cpp index c264869..2c631ad 100644 --- a/libraries/networking/message/AxonBinaryStream.cpp +++ b/libraries/networking/message/AxonBinaryStream.cpp @@ -64,7 +64,7 @@ namespace Networking { return *this; } - void Networking::AxonBinaryStreamBase::append(const char* data, std::size_t dataSize) + void AxonBinaryStreamBase::append(const char* data, std::size_t dataSize) { char* containerBufferPointer = new char[containerSize + dataSize]; memcpy(containerBufferPointer, containerPtr, containerSize); @@ -74,7 +74,7 @@ namespace Networking { containerSize += dataSize; } - void Networking::AxonBinaryStreamBase::clear() { + void AxonBinaryStreamBase::clear() { delete[] containerPtr; containerSize = 0; } diff --git a/libraries/networking/message/AxonBinaryStream.hpp b/libraries/networking/message/AxonBinaryStream.hpp index a7dff77..2066f98 100644 --- a/libraries/networking/message/AxonBinaryStream.hpp +++ b/libraries/networking/message/AxonBinaryStream.hpp @@ -17,8 +17,8 @@ namespace Networking { /* API */ void append(const char*, size_t); - inline const char* data() const noexcept { return containerPtr; } - inline size_t size() const noexcept { return containerSize; } + const char* data() const noexcept { return containerPtr; } + size_t size() const noexcept { return containerSize; } void clear(); private: char* containerPtr = nullptr; diff --git a/libraries/networking/message/AxonMessage.cpp b/libraries/networking/message/AxonMessage.cpp index 0ee9198..cbb9303 100644 --- a/libraries/networking/message/AxonMessage.cpp +++ b/libraries/networking/message/AxonMessage.cpp @@ -93,7 +93,6 @@ Networking::AxonMessage::AxonMessage(const void* message, size64_t size, uint8_t Networking::AxonMessage::AxonMessage(const SerializedAxonMessage &serialized) { TAG_T tag; - deserialize( serialized.bytes, serialized.size, @@ -101,10 +100,16 @@ Networking::AxonMessage::AxonMessage(const SerializedAxonMessage &serialized) &this->size, &tag ); - decompressTag(tag, &partID, &flags, &this->uniqueID); } +Networking::AxonMessage::AxonMessage(const AxonMessage &message, const uint8_t additionalFlags) : + flags(additionalFlags), + uniqueID(message.uniqueID) +{ + addFlag(ACKNOWLEDGE); +} + Networking::AxonMessage::AxonMessage(const AxonMessage& message) : size(message.size), partID(message.partID), @@ -118,7 +123,7 @@ Networking::AxonMessage::AxonMessage(const AxonMessage& message) : memcpy(this->message, message.getMessage(), this->size); } -Networking::AxonMessage::AxonMessage(Networking::AxonMessage &message, size64_t size, uint8_t partID, uint8_t flags, uint64_t uniqueID, size64_t offset) : +Networking::AxonMessage::AxonMessage(AxonMessage &message, size64_t size, uint8_t partID, uint8_t flags, uint64_t uniqueID, size64_t offset) : size(size), message(message.message), partID(partID), @@ -184,13 +189,6 @@ void Networking::AxonMessage::append(const Networking::AxonMessage &other) { partID = other.partID; } -Networking::AxonMessage::AxonMessage(const AxonMessage &message, uint8_t additionalFlags) : - flags(additionalFlags), - uniqueID(message.uniqueID) -{ - addFlag(ACKNOWLEDGE); -} - #pragma endregion /* AxonMessage.cpp */ diff --git a/libraries/networking/message/AxonMessage.hpp b/libraries/networking/message/AxonMessage.hpp index cfff75e..2e4b7c9 100644 --- a/libraries/networking/message/AxonMessage.hpp +++ b/libraries/networking/message/AxonMessage.hpp @@ -12,8 +12,8 @@ namespace Networking { - /* - * MESSAGE TAG STRUCTURE: + /** + * MESSAGE TAG STRUCTURE: * * 8 bits of optional message data (such as partialID) * 8 bits of TAG_FLAGS @@ -26,18 +26,17 @@ namespace Networking */ enum TAG_FLAGS { - UNDEFINED = 0, /// default - VALIDATE = 1, /// "how copy?" - ACKNOWLEDGE = 1 << 1, /// response package, "copy that!" - PARTIAL = 1 << 2, /// set if message bits are part of a partial delivery + UNDEFINED = 0, ///< default + VALIDATE = 1, ///< "how copy?" + ACKNOWLEDGE = 1 << 1, ///< response package, "copy that!" + PARTIAL = 1 << 2, ///< set if message bits are part of a partial delivery ALL = UNDEFINED | VALIDATE | ACKNOWLEDGE | PARTIAL }; static_assert(ALL == 0b111, "Flag set is incorrect. Check ALL value or manually edit this assert"); - class AxonMessage; - /* + /** * Class, optimized for queued storage, bit split */ class AXON_DECLSPEC SerializedAxonMessage { @@ -67,43 +66,59 @@ namespace Networking friend class AxonMessage; }; - /* - * AxonMessage is a low-level interface for data storage, serialization and network sharing + /** + * AxonMessage is a low-level interface for data storage, serialization and network sharing. + * + * Can be created in several ways. See constructors */ class AXON_DECLSPEC AxonMessage { public: typedef std::unique_ptr UniqueAxonMessagePtr; AxonMessage() = default; + + protected: /** * Create new message from actual data (send mode) + * @param message data pointer + * @param size message size, bytes + * @param partID optional parameter + * @param flags optional parameter, flag set */ - AxonMessage(const void*, size64_t, uint8_t = 0, uint8_t = 0); + AxonMessage(const void* message, size64_t size, uint8_t partID=0, uint8_t flags=0); + public: /** - * Create new message from serialized message structure (preferred) + * Create new message from serialized. + * @param serialized SerializedAxonMessage object, containing compressed data */ - explicit AxonMessage(const SerializedAxonMessage&); + explicit AxonMessage(const SerializedAxonMessage &serialized); /** * Create acknowledge message with empty buffer + * @param message message to create acknowledge message from (will copy uniqueID) + * @param additionalFlags flags to add */ - AxonMessage(const AxonMessage&, uint8_t); + AxonMessage(const AxonMessage &message, uint8_t additionalFlags); - AxonMessage(const AxonMessage&); + /** + * Copy constructor + */ + AxonMessage(const AxonMessage &); + private: AxonMessage(AxonMessage&, size64_t, uint8_t, uint8_t, uint64_t, size64_t); + public: ~AxonMessage(); WGETTER(SerializedAxonMessage getSerialized()); WGETTER(void* getMessage()) { return (message) ? static_cast(static_cast(message) + offset) : message; } WGETTER(size64_t getSize()) { return size; } WGETTER(uint16_t ID()) { return uniqueID; } - GETTER uint8_t getFlags() const { return flags; } - GETTER uint8_t getPartID() const { return partID; } - GETTER bool hasFlag(const TAG_FLAGS flag) const { return flags & flag; } + WGETTER(uint8_t getFlags()) { return flags; } + WGETTER(uint8_t getPartID()) { return partID; } + WGETTER(bool hasFlag(const TAG_FLAGS flag)) { return flags & flag; } - // Mostly for debugging - GETTER std::bitset<8> getFlagSet() const noexcept { return { flags }; } + WGETTER(std::bitset<8> getFlagSet()) { return flags; } void setPartID(const uint8_t id) { this->partID = id; } @@ -120,7 +135,7 @@ namespace Networking uniqueID = 0; return uniqueID++; } - void decompressTag(TAG_T, uint8_t*, uint8_t*, uint16_t*); + static void decompressTag(TAG_T, uint8_t*, uint8_t*, uint16_t*); private: size64_t size = 0; void* message = nullptr; From 8f47e19b790f96ee6239eba3c7b22577ca22e564 Mon Sep 17 00:00:00 2001 From: Keyboard Destroyer Date: Sun, 1 Jun 2025 16:19:01 +0300 Subject: [PATCH 18/47] Fix build issues --- libraries/events/AxonEvent.cpp | 2 +- libraries/networking/message/AxonMessage.hpp | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/libraries/events/AxonEvent.cpp b/libraries/events/AxonEvent.cpp index 145067f..d425504 100644 --- a/libraries/events/AxonEvent.cpp +++ b/libraries/events/AxonEvent.cpp @@ -22,7 +22,7 @@ void EventSystem::AxonEventManager::invoke(AxonEvent* event) } } -EventSystem::GlobalEventManager& EventSystem::GlobalEventManager::Instance() +EventSystem::GlobalEventManager& EventSystem::GlobalEventManager::Instance() noexcept { static GlobalEventManager instance; return instance; diff --git a/libraries/networking/message/AxonMessage.hpp b/libraries/networking/message/AxonMessage.hpp index 2e4b7c9..2e4a57f 100644 --- a/libraries/networking/message/AxonMessage.hpp +++ b/libraries/networking/message/AxonMessage.hpp @@ -77,7 +77,6 @@ namespace Networking typedef std::unique_ptr UniqueAxonMessagePtr; AxonMessage() = default; - protected: /** * Create new message from actual data (send mode) * @param message data pointer @@ -87,7 +86,6 @@ namespace Networking */ AxonMessage(const void* message, size64_t size, uint8_t partID=0, uint8_t flags=0); - public: /** * Create new message from serialized. * @param serialized SerializedAxonMessage object, containing compressed data @@ -105,9 +103,7 @@ namespace Networking * Copy constructor */ AxonMessage(const AxonMessage &); - private: AxonMessage(AxonMessage&, size64_t, uint8_t, uint8_t, uint64_t, size64_t); - public: ~AxonMessage(); WGETTER(SerializedAxonMessage getSerialized()); From 98d14db8e4b9d8613d0ccdb93881d9e5191daf26 Mon Sep 17 00:00:00 2001 From: Keyboard Destroyer Date: Sun, 1 Jun 2025 16:21:11 +0300 Subject: [PATCH 19/47] Fix build --- libraries/backends/berkeley/tcp/tcp_connection.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/backends/berkeley/tcp/tcp_connection.h b/libraries/backends/berkeley/tcp/tcp_connection.h index 28bc489..1e21db5 100644 --- a/libraries/backends/berkeley/tcp/tcp_connection.h +++ b/libraries/backends/berkeley/tcp/tcp_connection.h @@ -9,7 +9,7 @@ uint8_t connect_tcp_client(SOCKADDR_IN_T *, SOCKET_T *, const char *, uint32_t); uint8_t create_tcp_server(SOCKADDR_IN_T*, SOCKET_T*, uint32_t); int32_t send_tcp_message(const void*, size_t, SOCKET_T); int32_t recv_tcp_message(void*, size_t, SOCKET_T); -SOCKET_T accept_incoming(SOCKET_T, SOCKADDR_IN_T*); +SOCKET_T accept_incoming(SOCKET_T, const SOCKADDR_IN_T*); void finalize_tcp(SOCKET_T); #pragma endregion From a63622d4f639554ee220fe297ec1df4ff81c1dfb Mon Sep 17 00:00:00 2001 From: Keyboard Destroyer Date: Sun, 1 Jun 2025 20:03:48 +0300 Subject: [PATCH 20/47] added draft on network pointer --- libraries/networking/AxonNetwork.hpp | 3 ++ .../networking-core/BasicSynapse.hpp | 50 ++++++++++++++----- .../networking/networking-core/Synapse.hpp | 5 -- .../networking/utility/AxonNetworkPointer.cpp | 24 +++++++++ .../networking/utility/AxonNetworkPointer.hpp | 32 ++++++++++++ 5 files changed, 96 insertions(+), 18 deletions(-) create mode 100644 libraries/networking/utility/AxonNetworkPointer.cpp create mode 100644 libraries/networking/utility/AxonNetworkPointer.hpp diff --git a/libraries/networking/AxonNetwork.hpp b/libraries/networking/AxonNetwork.hpp index ce9d39a..0868200 100644 --- a/libraries/networking/AxonNetwork.hpp +++ b/libraries/networking/AxonNetwork.hpp @@ -9,6 +9,9 @@ namespace Networking { + class AXON_DECLSPEC AxonNetworkManager { + + }; } /* AxonNetwork.hpp */ diff --git a/libraries/networking/networking-core/BasicSynapse.hpp b/libraries/networking/networking-core/BasicSynapse.hpp index 6e065b1..6e8a98a 100644 --- a/libraries/networking/networking-core/BasicSynapse.hpp +++ b/libraries/networking/networking-core/BasicSynapse.hpp @@ -10,10 +10,38 @@ #include #include #include +#include #include namespace Networking { + /** + * Non-template class that can be used as Synapse pointer + */ + class AXON_DECLSPEC SynapseInterface { + public: + SynapseInterface() = default; + virtual ~SynapseInterface(); + + WGETTER ( bool alive() ) { return isAlive.load(); } + virtual void kill() { isAlive.store(false); } + + virtual void start() = 0; + virtual void send(AxonMessage &) = 0; + virtual void sendTo(AxonMessage&, const Socket&) = 0; + virtual void sendTo(const SerializedAxonMessage&, const Socket&) const = 0; + + EventSystem::AxonEventManager& getEventManager() { return events; } + virtual void listen() = 0; + virtual void update() = 0; + virtual void onMessageReceived(const AxonMessage&, const Socket&) = 0; + protected: + std::atomic isAlive = false; + EventSystem::AxonEventManager events; + }; + + typedef SynapseInterface* SynapseInterfacePtr; + /** * Basic connection handler * Specifies one-to-one connection for client and one-to-many for server. @@ -21,7 +49,7 @@ namespace Networking { * @tparam conn connection mode (TCP|UDP) * @tparam mode synapse mode (CLIENT|SERVER) */ - template class AXON_DECLSPEC BasicSynapse + template class AXON_DECLSPEC BasicSynapse : public SynapseInterface { public: /** Default creation is restricted */ @@ -31,24 +59,20 @@ namespace Networking { /** Initialize Synapse in client mode */ explicit BasicSynapse(const ConnectionInfo&); - virtual ~BasicSynapse(); - - GETTER bool alive() const { return isAlive.load(); }; - virtual void kill() { isAlive.store(false); } + ~BasicSynapse() override; - virtual void start(); - virtual void send(AxonMessage&); - virtual void sendTo(AxonMessage&, const Socket&); - virtual void sendTo(const SerializedAxonMessage&, const Socket&) const; + void start() override; + void send(AxonMessage&) override; + void sendTo(AxonMessage&, const Socket&) override; + void sendTo(const SerializedAxonMessage&, const Socket&) const override; // This function should be instanced for each connection type - virtual void listen() {} - virtual void update() {} - virtual void onMessageReceived(const AxonMessage&, const Socket&) {}; + void listen() override {} + void update() override {} + void onMessageReceived(const AxonMessage&, const Socket&) override {}; void processIncomingMessage(const SerializedAxonMessage&, const Socket&); protected: - std::atomic isAlive = false; // TODO: move this from here ConnectionInfo connectionInfo; Socket socketInfo; }; diff --git a/libraries/networking/networking-core/Synapse.hpp b/libraries/networking/networking-core/Synapse.hpp index cd84cae..d0f0dc2 100644 --- a/libraries/networking/networking-core/Synapse.hpp +++ b/libraries/networking/networking-core/Synapse.hpp @@ -14,7 +14,6 @@ #include #include -#include namespace Networking { @@ -37,17 +36,13 @@ namespace Networking #pragma endregion #pragma region INTERFACE - void update() override; void onMessageReceived(const AxonMessage&, const Socket&) override; - EventSystem::AxonEventManager& getEventManager() { return events; } void sendTo(AxonMessage&, const Socket&) override; void sendPooled(const AxonMessage&, const Socket &) const; #pragma endregion protected: - EventSystem::AxonEventManager events; - std::vector pendingValidation; std::unique_ptr pool = std::make_unique(); std::unique_ptr mmap = std::make_unique(); diff --git a/libraries/networking/utility/AxonNetworkPointer.cpp b/libraries/networking/utility/AxonNetworkPointer.cpp new file mode 100644 index 0000000..1bdbc1d --- /dev/null +++ b/libraries/networking/utility/AxonNetworkPointer.cpp @@ -0,0 +1,24 @@ +#include "AxonNetworkPointer.hpp" + +namespace Networking { + AxonNetworkPointerBase::AxonNetworkPointerBase(SynapseInterfacePtr synapse) : + synapse(synapse) { + synapse->getEventManager().subscribe( + onSynapseDispatchedMessageReceiveEvent, + this + ); + } + + void AxonNetworkPointerBase::sendSelf() { + beforeSend(); + AxonMessage message = this->toMessage(); + synapse->send(message); + onSend(); + } + + void AxonNetworkPointerBase::onSynapseDispatchedMessageReceiveEvent(const SynapseMessageReceivedEvent &event) { + if (this->fromMessage(event.getMessage())) { + onReceivedNetworkData(); + } + } +} // Networking \ No newline at end of file diff --git a/libraries/networking/utility/AxonNetworkPointer.hpp b/libraries/networking/utility/AxonNetworkPointer.hpp new file mode 100644 index 0000000..05e3bf1 --- /dev/null +++ b/libraries/networking/utility/AxonNetworkPointer.hpp @@ -0,0 +1,32 @@ +#pragma once +#include + + +namespace Networking { + class AXON_DECLSPEC AxonNetworkPointerBase { + public: + AxonNetworkPointerBase() = delete; + explicit AxonNetworkPointerBase(SynapseInterfacePtr); + virtual ~AxonNetworkPointerBase() = default; + + GETTER EventSystem::AxonEventManager& getEventManager() { return events; } + protected: + virtual AxonMessage toMessage() = 0; + virtual bool fromMessage(const AxonMessage&) = 0; + void sendSelf(); + virtual void beforeSend() = 0; + virtual void onSend() = 0; + + void onSynapseDispatchedMessageReceiveEvent(const SynapseMessageReceivedEvent&); + virtual void onReceivedNetworkData() = 0; + private: + SynapseInterfacePtr synapse = nullptr; + EventSystem::AxonEventManager events; + }; + + template + class AXON_DECLSPEC AxonNetworkPointer : public AxonNetworkPointerBase { + + }; +} // Networking + From 91223917aeedf2d1c46dd549d2f6b1c1f12e37a3 Mon Sep 17 00:00:00 2001 From: Keyboard Destroyer Date: Sun, 1 Jun 2025 20:06:53 +0300 Subject: [PATCH 21/47] fix build issue --- libraries/networking/networking-core/BasicSynapse.hpp | 2 +- libraries/networking/utility/AxonNetworkPointer.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/networking/networking-core/BasicSynapse.hpp b/libraries/networking/networking-core/BasicSynapse.hpp index 6e8a98a..e01f398 100644 --- a/libraries/networking/networking-core/BasicSynapse.hpp +++ b/libraries/networking/networking-core/BasicSynapse.hpp @@ -21,7 +21,7 @@ namespace Networking { class AXON_DECLSPEC SynapseInterface { public: SynapseInterface() = default; - virtual ~SynapseInterface(); + virtual ~SynapseInterface() = default; WGETTER ( bool alive() ) { return isAlive.load(); } virtual void kill() { isAlive.store(false); } diff --git a/libraries/networking/utility/AxonNetworkPointer.cpp b/libraries/networking/utility/AxonNetworkPointer.cpp index 1bdbc1d..e1d32a5 100644 --- a/libraries/networking/utility/AxonNetworkPointer.cpp +++ b/libraries/networking/utility/AxonNetworkPointer.cpp @@ -4,7 +4,7 @@ namespace Networking { AxonNetworkPointerBase::AxonNetworkPointerBase(SynapseInterfacePtr synapse) : synapse(synapse) { synapse->getEventManager().subscribe( - onSynapseDispatchedMessageReceiveEvent, + &AxonNetworkPointerBase::onSynapseDispatchedMessageReceiveEvent, this ); } From e4c39bb2a792a7322a0093c603cfc9363dd41116 Mon Sep 17 00:00:00 2001 From: Keyboard Destroyer Date: Mon, 2 Jun 2025 19:50:29 +0300 Subject: [PATCH 22/47] Replace event - this->event --- libraries/networking/networking-core/Synapse.ipp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/networking/networking-core/Synapse.ipp b/libraries/networking/networking-core/Synapse.ipp index ce523b1..c91824d 100644 --- a/libraries/networking/networking-core/Synapse.ipp +++ b/libraries/networking/networking-core/Synapse.ipp @@ -57,8 +57,8 @@ void Networking::Synapse::onMessageReceived(const AxonMessage& messa if (!res) return; - SynapseMessageReceivedEvent event_ = SynapseMessageReceivedEvent(*res, from); - events.invoke(&event_); + SynapseMessageReceivedEvent event_(*res, from); + this->events.invoke(&event_); } return; } From 98656cd468cb54a088e7ac728e0cbda5a68286a5 Mon Sep 17 00:00:00 2001 From: Keyboard Destroyer Date: Mon, 2 Jun 2025 19:56:55 +0300 Subject: [PATCH 23/47] Replace event - this->event --- libraries/networking/networking-core/Synapse.ipp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/networking/networking-core/Synapse.ipp b/libraries/networking/networking-core/Synapse.ipp index c91824d..a284894 100644 --- a/libraries/networking/networking-core/Synapse.ipp +++ b/libraries/networking/networking-core/Synapse.ipp @@ -64,7 +64,7 @@ void Networking::Synapse::onMessageReceived(const AxonMessage& messa } SynapseMessageReceivedEvent event_ = SynapseMessageReceivedEvent(message, from); - events.invoke(&event_); + this->events.invoke(&event_); } #pragma endregion From ea643107de0bb90939227917a4e2075f2d6b815c Mon Sep 17 00:00:00 2001 From: Keyboard Destroyer Date: Mon, 2 Jun 2025 20:05:49 +0300 Subject: [PATCH 24/47] Fixed includes --- examples/basics/basic-synapse/client.cpp | 1 - libraries/networking/AxonNetwork.hpp | 2 ++ .../networking/networking-core/Synapse.hpp | 4 +-- .../networking/utility/AxonNetworkPointer.cpp | 19 -------------- .../networking/utility/AxonNetworkPointer.hpp | 26 +------------------ 5 files changed, 4 insertions(+), 48 deletions(-) diff --git a/examples/basics/basic-synapse/client.cpp b/examples/basics/basic-synapse/client.cpp index e96a63e..d538111 100644 --- a/examples/basics/basic-synapse/client.cpp +++ b/examples/basics/basic-synapse/client.cpp @@ -7,7 +7,6 @@ */ #include -#include #include #include diff --git a/libraries/networking/AxonNetwork.hpp b/libraries/networking/AxonNetwork.hpp index b26b419..30604a1 100644 --- a/libraries/networking/AxonNetwork.hpp +++ b/libraries/networking/AxonNetwork.hpp @@ -3,6 +3,8 @@ #include #include #include +#include +#include namespace Networking { diff --git a/libraries/networking/networking-core/Synapse.hpp b/libraries/networking/networking-core/Synapse.hpp index 94ddafa..59e0684 100644 --- a/libraries/networking/networking-core/Synapse.hpp +++ b/libraries/networking/networking-core/Synapse.hpp @@ -1,14 +1,12 @@ #pragma once #include -#include #include #include #include -#include -#include #include +#include namespace Networking { diff --git a/libraries/networking/utility/AxonNetworkPointer.cpp b/libraries/networking/utility/AxonNetworkPointer.cpp index e1d32a5..fa28cf0 100644 --- a/libraries/networking/utility/AxonNetworkPointer.cpp +++ b/libraries/networking/utility/AxonNetworkPointer.cpp @@ -1,24 +1,5 @@ #include "AxonNetworkPointer.hpp" namespace Networking { - AxonNetworkPointerBase::AxonNetworkPointerBase(SynapseInterfacePtr synapse) : - synapse(synapse) { - synapse->getEventManager().subscribe( - &AxonNetworkPointerBase::onSynapseDispatchedMessageReceiveEvent, - this - ); - } - void AxonNetworkPointerBase::sendSelf() { - beforeSend(); - AxonMessage message = this->toMessage(); - synapse->send(message); - onSend(); - } - - void AxonNetworkPointerBase::onSynapseDispatchedMessageReceiveEvent(const SynapseMessageReceivedEvent &event) { - if (this->fromMessage(event.getMessage())) { - onReceivedNetworkData(); - } - } } // Networking \ No newline at end of file diff --git a/libraries/networking/utility/AxonNetworkPointer.hpp b/libraries/networking/utility/AxonNetworkPointer.hpp index 05e3bf1..4f95f2d 100644 --- a/libraries/networking/utility/AxonNetworkPointer.hpp +++ b/libraries/networking/utility/AxonNetworkPointer.hpp @@ -1,32 +1,8 @@ #pragma once -#include +#include namespace Networking { - class AXON_DECLSPEC AxonNetworkPointerBase { - public: - AxonNetworkPointerBase() = delete; - explicit AxonNetworkPointerBase(SynapseInterfacePtr); - virtual ~AxonNetworkPointerBase() = default; - GETTER EventSystem::AxonEventManager& getEventManager() { return events; } - protected: - virtual AxonMessage toMessage() = 0; - virtual bool fromMessage(const AxonMessage&) = 0; - void sendSelf(); - virtual void beforeSend() = 0; - virtual void onSend() = 0; - - void onSynapseDispatchedMessageReceiveEvent(const SynapseMessageReceivedEvent&); - virtual void onReceivedNetworkData() = 0; - private: - SynapseInterfacePtr synapse = nullptr; - EventSystem::AxonEventManager events; - }; - - template - class AXON_DECLSPEC AxonNetworkPointer : public AxonNetworkPointerBase { - - }; } // Networking From a8d52468d73866b8853c971c69216ec7578ec806 Mon Sep 17 00:00:00 2001 From: KbrdDestroyer Date: Tue, 3 Jun 2025 11:37:42 +0300 Subject: [PATCH 25/47] Moved message to separate library --- .../message => messages}/AxonBinaryStream.cpp | 0 .../message => messages}/AxonBinaryStream.hpp | 2 +- .../message => messages}/AxonMessage.cpp | 0 .../message => messages}/AxonMessage.hpp | 2 +- libraries/messages/CMakeLists.txt | 15 +++++++++++++++ libraries/networking/AxonNetwork.hpp | 12 ++++++------ libraries/networking/CMakeLists.txt | 2 +- .../{networking-core => synapse}/BasicSynapse.hpp | 6 +++--- .../{networking-core => synapse}/BasicSynapse.ipp | 7 +++---- .../{networking-core => synapse}/Synapse.hpp | 10 +++++----- .../{networking-core => synapse}/Synapse.ipp | 0 .../utils}/SynapseEvents.cpp | 0 .../utils}/SynapseEvents.hpp | 6 +++--- .../utils}/SynapseUtility.cpp | 4 ++-- .../utils}/SynapseUtility.hpp | 6 +++--- .../networking/utility/AxonNetworkPointer.hpp | 2 +- libraries/networking/utility/MessagePool.hpp | 2 +- tests/gtest/test_serialization.cpp | 2 +- tests/performance/perf_message_api.cpp | 2 +- 19 files changed, 47 insertions(+), 33 deletions(-) rename libraries/{networking/message => messages}/AxonBinaryStream.cpp (100%) rename libraries/{networking/message => messages}/AxonBinaryStream.hpp (96%) rename libraries/{networking/message => messages}/AxonMessage.cpp (100%) rename libraries/{networking/message => messages}/AxonMessage.hpp (99%) create mode 100644 libraries/messages/CMakeLists.txt rename libraries/networking/{networking-core => synapse}/BasicSynapse.hpp (94%) rename libraries/networking/{networking-core => synapse}/BasicSynapse.ipp (97%) rename libraries/networking/{networking-core => synapse}/Synapse.hpp (90%) rename libraries/networking/{networking-core => synapse}/Synapse.ipp (100%) rename libraries/networking/{networking-core => synapse/utils}/SynapseEvents.cpp (100%) rename libraries/networking/{networking-core => synapse/utils}/SynapseEvents.hpp (86%) rename libraries/networking/{networking-core => synapse/utils}/SynapseUtility.cpp (90%) rename libraries/networking/{networking-core => synapse/utils}/SynapseUtility.hpp (90%) diff --git a/libraries/networking/message/AxonBinaryStream.cpp b/libraries/messages/AxonBinaryStream.cpp similarity index 100% rename from libraries/networking/message/AxonBinaryStream.cpp rename to libraries/messages/AxonBinaryStream.cpp diff --git a/libraries/networking/message/AxonBinaryStream.hpp b/libraries/messages/AxonBinaryStream.hpp similarity index 96% rename from libraries/networking/message/AxonBinaryStream.hpp rename to libraries/messages/AxonBinaryStream.hpp index f6bb653..a92b522 100644 --- a/libraries/networking/message/AxonBinaryStream.hpp +++ b/libraries/messages/AxonBinaryStream.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include "AxonUtility.h" namespace Networking { class AXON_DECLSPEC AxonBinaryStreamBase { diff --git a/libraries/networking/message/AxonMessage.cpp b/libraries/messages/AxonMessage.cpp similarity index 100% rename from libraries/networking/message/AxonMessage.cpp rename to libraries/messages/AxonMessage.cpp diff --git a/libraries/networking/message/AxonMessage.hpp b/libraries/messages/AxonMessage.hpp similarity index 99% rename from libraries/networking/message/AxonMessage.hpp rename to libraries/messages/AxonMessage.hpp index 0ae052b..6b7254b 100644 --- a/libraries/networking/message/AxonMessage.hpp +++ b/libraries/messages/AxonMessage.hpp @@ -3,7 +3,7 @@ // TODO: Code styling, remove all shit pls #pragma once -#include +#include "serialization/serialization.hpp" #include #include diff --git a/libraries/messages/CMakeLists.txt b/libraries/messages/CMakeLists.txt new file mode 100644 index 0000000..3c7aa34 --- /dev/null +++ b/libraries/messages/CMakeLists.txt @@ -0,0 +1,15 @@ +project ("AxonEngine.libraries.messages") + +file(GLOB_RECURSE SOURCES + "${CMAKE_CURRENT_SOURCE_DIR}/*.c" + "${CMAKE_CURRENT_SOURCE_DIR}/*.h" + "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/*.hpp" + "${CMAKE_CURRENT_SOURCE_DIR}/*.ipp" +) + +add_library(messages STATIC ${SOURCES}) +set (LIB_HOME ${CMAKE_HOME_DIRECTORY}/libraries) +target_compile_definitions(messages PUBLIC AXON_LIB) +target_link_libraries(messages events serialization backends) +target_include_directories(messages PUBLIC "${LIB_HOME}") diff --git a/libraries/networking/AxonNetwork.hpp b/libraries/networking/AxonNetwork.hpp index 6749185..cda2d9e 100644 --- a/libraries/networking/AxonNetwork.hpp +++ b/libraries/networking/AxonNetwork.hpp @@ -1,13 +1,13 @@ #pragma once -#include -#include -#include -#include +#include "messages/AxonBinaryStream.hpp" +#include "networking/synapse/utils/SynapseEvents.hpp" +#include "networking/synapse/utils/SynapseUtility.hpp" +#include #include #include -#include -#include +#include "networking/synapse/utils/SynapseEvents.hpp" +#include namespace Networking { diff --git a/libraries/networking/CMakeLists.txt b/libraries/networking/CMakeLists.txt index 868d64d..44a90a9 100644 --- a/libraries/networking/CMakeLists.txt +++ b/libraries/networking/CMakeLists.txt @@ -12,7 +12,7 @@ add_library(networking SHARED ${SOURCES}) set (LIB_HOME ${CMAKE_HOME_DIRECTORY}/libraries) target_compile_definitions(networking PUBLIC AXON_LIB) -target_link_libraries(networking events serialization backends) +target_link_libraries(networking events serialization backends messages) target_include_directories(networking PUBLIC "${LIB_HOME}") target_include_directories(networking PUBLIC "${LIB_HOME}/networking") diff --git a/libraries/networking/networking-core/BasicSynapse.hpp b/libraries/networking/synapse/BasicSynapse.hpp similarity index 94% rename from libraries/networking/networking-core/BasicSynapse.hpp rename to libraries/networking/synapse/BasicSynapse.hpp index 351a130..4c3632d 100644 --- a/libraries/networking/networking-core/BasicSynapse.hpp +++ b/libraries/networking/synapse/BasicSynapse.hpp @@ -8,9 +8,9 @@ #pragma once #include -#include -#include -#include +#include "networking/synapse/utils/SynapseUtility.hpp" +#include "messages/AxonMessage.hpp" +#include "networking/synapse/utils/SynapseEvents.hpp" namespace Networking { diff --git a/libraries/networking/networking-core/BasicSynapse.ipp b/libraries/networking/synapse/BasicSynapse.ipp similarity index 97% rename from libraries/networking/networking-core/BasicSynapse.ipp rename to libraries/networking/synapse/BasicSynapse.ipp index d4c2c79..fd7f8f8 100644 --- a/libraries/networking/networking-core/BasicSynapse.ipp +++ b/libraries/networking/synapse/BasicSynapse.ipp @@ -1,5 +1,5 @@ #pragma once - +#include "networking/synapse/utils/SynapseUtility.hpp" namespace Networking { template<> @@ -20,13 +20,12 @@ template Networking::BasicSynapse::BasicSynapse(uint32_t port) { connectionInfo.port = port; - socketInfo = {}; uint8_t result = initialize_server(socketInfo, port); if (result != SUCCESS) { - throw AxonNetworkingInternalError(result); + throw Networking::AxonNetworkingInternalError(result); } } @@ -41,7 +40,7 @@ Networking::BasicSynapse::BasicSynapse(const ConnectionInfo& connect uint8_t result = initialize_client(socketInfo, connection.hostname.c_str(), connection.port); if (result != SUCCESS) { - throw AxonNetworkingInternalError(result); + throw Networking::AxonNetworkingInternalError(result); } } diff --git a/libraries/networking/networking-core/Synapse.hpp b/libraries/networking/synapse/Synapse.hpp similarity index 90% rename from libraries/networking/networking-core/Synapse.hpp rename to libraries/networking/synapse/Synapse.hpp index c343335..ad71187 100644 --- a/libraries/networking/networking-core/Synapse.hpp +++ b/libraries/networking/synapse/Synapse.hpp @@ -1,12 +1,12 @@ #pragma once -#include -#include +#include "BasicSynapse.hpp" +#include "networking/utility/MessagePool.hpp" #include -#include -#include +#include "AxonUtility.h" +#include "messages/AxonMessage.hpp" -#include +#include "networking/synapse/utils/SynapseUtility.hpp" namespace Networking { diff --git a/libraries/networking/networking-core/Synapse.ipp b/libraries/networking/synapse/Synapse.ipp similarity index 100% rename from libraries/networking/networking-core/Synapse.ipp rename to libraries/networking/synapse/Synapse.ipp diff --git a/libraries/networking/networking-core/SynapseEvents.cpp b/libraries/networking/synapse/utils/SynapseEvents.cpp similarity index 100% rename from libraries/networking/networking-core/SynapseEvents.cpp rename to libraries/networking/synapse/utils/SynapseEvents.cpp diff --git a/libraries/networking/networking-core/SynapseEvents.hpp b/libraries/networking/synapse/utils/SynapseEvents.hpp similarity index 86% rename from libraries/networking/networking-core/SynapseEvents.hpp rename to libraries/networking/synapse/utils/SynapseEvents.hpp index 494dbe8..256ca87 100644 --- a/libraries/networking/networking-core/SynapseEvents.hpp +++ b/libraries/networking/synapse/utils/SynapseEvents.hpp @@ -1,7 +1,7 @@ #pragma once -#include -#include -#include +#include "events/AxonEvent.hpp" +#include "messages/AxonMessage.hpp" +#include "AxonUtility.h" struct Socket; diff --git a/libraries/networking/networking-core/SynapseUtility.cpp b/libraries/networking/synapse/utils/SynapseUtility.cpp similarity index 90% rename from libraries/networking/networking-core/SynapseUtility.cpp rename to libraries/networking/synapse/utils/SynapseUtility.cpp index 6fbc48b..1dff993 100644 --- a/libraries/networking/networking-core/SynapseUtility.cpp +++ b/libraries/networking/synapse/utils/SynapseUtility.cpp @@ -1,5 +1,5 @@ #include "SynapseUtility.hpp" -#include +#include "common_macro.h" namespace Networking { const char * AxonNetworkingInternalError::what() const noexcept { @@ -10,7 +10,7 @@ namespace Networking { #if defined(WINDOWS_PLATFORM) return "C WSAStartup function failed."; #else - return "That shouln't be here. Check your code"; + return "That shouldn't be here. Check your code"; #endif case ERR_INVALID: return "Got invalid socket value"; diff --git a/libraries/networking/networking-core/SynapseUtility.hpp b/libraries/networking/synapse/utils/SynapseUtility.hpp similarity index 90% rename from libraries/networking/networking-core/SynapseUtility.hpp rename to libraries/networking/synapse/utils/SynapseUtility.hpp index a01455f..715bff7 100644 --- a/libraries/networking/networking-core/SynapseUtility.hpp +++ b/libraries/networking/synapse/utils/SynapseUtility.hpp @@ -1,8 +1,8 @@ #pragma once #include -#include -#include +#include "backends/backend.hpp" +#include "AxonUtility.h" namespace Networking { /** @@ -43,7 +43,7 @@ namespace Networking { const uint8_t err; public: explicit AxonNetworkingInternalError(const uint8_t err = 0) : err(err) {} - GETTER constexpr uint8_t code() const { return err; } + GETTER constexpr uint8_t code() const { return err; } GETTER const char* what() const noexcept override; }; } diff --git a/libraries/networking/utility/AxonNetworkPointer.hpp b/libraries/networking/utility/AxonNetworkPointer.hpp index 4f95f2d..97b34be 100644 --- a/libraries/networking/utility/AxonNetworkPointer.hpp +++ b/libraries/networking/utility/AxonNetworkPointer.hpp @@ -1,5 +1,5 @@ #pragma once -#include +#include "networking/synapse/utils/SynapseEvents.hpp" namespace Networking { diff --git a/libraries/networking/utility/MessagePool.hpp b/libraries/networking/utility/MessagePool.hpp index df66dcf..1a4d21f 100644 --- a/libraries/networking/utility/MessagePool.hpp +++ b/libraries/networking/utility/MessagePool.hpp @@ -1,5 +1,5 @@ #pragma once -#include +#include "messages/AxonMessage.hpp" #include #include #include diff --git a/tests/gtest/test_serialization.cpp b/tests/gtest/test_serialization.cpp index ff1c9f8..d533329 100644 --- a/tests/gtest/test_serialization.cpp +++ b/tests/gtest/test_serialization.cpp @@ -1,6 +1,6 @@ #include #include -#include +#include "messages/AxonMessage.hpp" #include diff --git a/tests/performance/perf_message_api.cpp b/tests/performance/perf_message_api.cpp index f2d49a3..9a80763 100644 --- a/tests/performance/perf_message_api.cpp +++ b/tests/performance/perf_message_api.cpp @@ -1,4 +1,4 @@ -#include +#include "messages/AxonMessage.hpp" #include int main() { From 4e0bf2d8262ef1533b654d06be9e9370c02faecf Mon Sep 17 00:00:00 2001 From: KbrdDestroyer Date: Tue, 3 Jun 2025 15:17:22 +0300 Subject: [PATCH 26/47] Moved networking logic to low-level controller --- libraries/messages/AxonBinaryStream.hpp | 11 +- libraries/networking/synapse/BasicSynapse.hpp | 45 ++--- libraries/networking/synapse/BasicSynapse.ipp | 167 ++---------------- libraries/networking/synapse/Synapse.ipp | 2 + .../networking/synapse/SynapseInterface.hpp | 31 ++++ .../netcontroller/AxonNetworkController.hpp | 55 ++++++ .../netcontroller/AxonNetworkController.ipp | 166 +++++++++++++++++ 7 files changed, 292 insertions(+), 185 deletions(-) create mode 100644 libraries/networking/synapse/SynapseInterface.hpp create mode 100644 libraries/networking/synapse/netcontroller/AxonNetworkController.hpp create mode 100644 libraries/networking/synapse/netcontroller/AxonNetworkController.ipp diff --git a/libraries/messages/AxonBinaryStream.hpp b/libraries/messages/AxonBinaryStream.hpp index a92b522..25e5edb 100644 --- a/libraries/messages/AxonBinaryStream.hpp +++ b/libraries/messages/AxonBinaryStream.hpp @@ -16,11 +16,16 @@ namespace Networking { /* API */ void append(const char*, size_t); - const char* data() const noexcept { return containerPtr; } - size_t size() const noexcept { return containerSize; } + GETTER const char* data() const noexcept { return containerPtr; } + GETTER size_t size() const noexcept { return containerSize; } void clear(); - private: + protected: char* containerPtr = nullptr; size_t containerSize = 0; }; + + class AXON_DECLSPEC AxonBinaryStream : public AxonBinaryStreamBase { + public: + AxonBinaryStream() = default; + }; } diff --git a/libraries/networking/synapse/BasicSynapse.hpp b/libraries/networking/synapse/BasicSynapse.hpp index 4c3632d..176a837 100644 --- a/libraries/networking/synapse/BasicSynapse.hpp +++ b/libraries/networking/synapse/BasicSynapse.hpp @@ -11,36 +11,11 @@ #include "networking/synapse/utils/SynapseUtility.hpp" #include "messages/AxonMessage.hpp" #include "networking/synapse/utils/SynapseEvents.hpp" +#include "SynapseInterface.hpp" +#include namespace Networking { - /** - * Non-template class that can be used as Synapse pointer - */ - class AXON_DECLSPEC SynapseInterface { - public: - SynapseInterface() = default; - virtual ~SynapseInterface() = default; - - WGETTER ( bool alive() ) { return isAlive.load(); } - virtual void kill() { isAlive.store(false); } - - virtual void start() = 0; - virtual void send(AxonMessage &) = 0; - virtual void sendTo(AxonMessage&, const Socket&) = 0; - virtual void sendTo(const SerializedAxonMessage&, const Socket&) const = 0; - - EventSystem::AxonEventManager& getEventManager() { return events; } - virtual void listen() = 0; - virtual void update() = 0; - virtual void onMessageReceived(const AxonMessage&, const Socket&) = 0; - protected: - std::atomic isAlive = false; - EventSystem::AxonEventManager events; - }; - - typedef SynapseInterface* SynapseInterfacePtr; - /** * Basic connection handler * Specifies one-to-one connection for client and one-to-many for server. @@ -48,7 +23,8 @@ namespace Networking { * @tparam conn connection mode (TCP|UDP) * @tparam mode synapse mode (CLIENT|SERVER) */ - template class AXON_DECLSPEC BasicSynapse : public SynapseInterface + template + class AXON_DECLSPEC BasicSynapse : public SynapseInterface { public: /** Default creation is restricted */ @@ -58,25 +34,30 @@ namespace Networking { /** Initialize Synapse in client mode */ explicit BasicSynapse(const ConnectionInfo&); + explicit BasicSynapse(const BasicSynapse&) = delete; + BasicSynapse(BasicSynapse&&) noexcept = delete; + BasicSynapse& operator=(const BasicSynapse&) = delete; + BasicSynapse& operator=(BasicSynapse&&) noexcept = delete; + ~BasicSynapse() override; void start() override; void send(AxonMessage&) override; void sendTo(AxonMessage&, const Socket&) override; - void sendTo(const SerializedAxonMessage&, const Socket&) const override; // This function should be instanced for each connection type - void listen() override {} + void listen() override; void update() override {} void onMessageReceived(const AxonMessage&, const Socket&) override {}; - void processIncomingMessage(const SerializedAxonMessage&, const Socket&); + void processIncomingMessage(const SerializedAxonMessage&, const Socket&) override; protected: ConnectionInfo connectionInfo; Socket socketInfo; + + std::unique_ptr> controller; }; } #include "BasicSynapse.ipp" - // BasicSynapse.hpp diff --git a/libraries/networking/synapse/BasicSynapse.ipp b/libraries/networking/synapse/BasicSynapse.ipp index fd7f8f8..8c25fb6 100644 --- a/libraries/networking/synapse/BasicSynapse.ipp +++ b/libraries/networking/synapse/BasicSynapse.ipp @@ -1,53 +1,28 @@ #pragma once #include "networking/synapse/utils/SynapseUtility.hpp" -namespace Networking { - template<> - void BasicSynapse::listen(); - template<> - void BasicSynapse::listen(); - template<> - void BasicSynapse::listen(); - template<> - void BasicSynapse::listen(); -} - #pragma region BASIC_SYNAPSE - #pragma region CONTRUCTING template -Networking::BasicSynapse::BasicSynapse(uint32_t port) -{ - connectionInfo.port = port; - socketInfo = {}; - - uint8_t result = initialize_server(socketInfo, port); - - if (result != SUCCESS) { - throw Networking::AxonNetworkingInternalError(result); - } -} +Networking::BasicSynapse::BasicSynapse(uint32_t port) : + connectionInfo({"", port}), + socketInfo(), + controller(std::make_unique>(this, port)) +{} template -Networking::BasicSynapse::BasicSynapse(const ConnectionInfo& connection) -{ - connectionInfo.hostname = connection.hostname; - connectionInfo.port = connection.port; - - socketInfo = {}; - - uint8_t result = initialize_client(socketInfo, connection.hostname.c_str(), connection.port); - - if (result != SUCCESS) { - throw Networking::AxonNetworkingInternalError(result); - } -} +Networking::BasicSynapse::BasicSynapse(const ConnectionInfo& connection) : + connectionInfo(connection), + socketInfo(), + controller(std::make_unique>(this, connection)) +{} template Networking::BasicSynapse::~BasicSynapse() { isAlive = false; + controller->kill(); finalize(socketInfo); } @@ -57,25 +32,20 @@ template void Networking::BasicSynapse::start() { isAlive.store(true); + controller->start(); listen(); } template void Networking::BasicSynapse::send(AxonMessage& message) { - sendTo(message, socketInfo); + controller->send(message); } template void Networking::BasicSynapse::sendTo(AxonMessage& message, const Socket& dest) { - sendTo(message.getSerialized(), dest); -} - -template -void Networking::BasicSynapse::sendTo(const SerializedAxonMessage& serialized, const Socket& dest) const -{ - send_message(dest, serialized.getBits(), serialized.getSize()); + controller->sendTo(message, dest); } template @@ -83,112 +53,9 @@ void Networking::BasicSynapse::processIncomingMessage(const Serializ onMessageReceived(AxonMessage(message), from); } -#pragma region SERVER_FUNCTIONS - -template<> -inline void Networking::BasicSynapse::listen() -{ - fd_set master; - FD_ZERO(&master); - FD_SET(socketInfo.socket, &master); - SOCKET_T maxSocket = socketInfo.socket; - - while (isAlive) - { - timeval tv = { 0, 10000 }; - fd_set reads = master; - if (select(maxSocket + 1, &reads, nullptr, nullptr, &tv) <= 0) { - continue; - } - for (SOCKET_T connectionSock = 1; connectionSock <= maxSocket; connectionSock++) { - if (FD_ISSET(connectionSock, &reads)){ - if (connectionSock == socketInfo.socket) { - sockaddr_storage storage = {}; - SOCKET_T client = accept_incoming(socketInfo.socket, reinterpret_cast(&storage)); - - if (!CHECK_VALID(client)) { - continue; - } - - FD_SET(client, &master); - if (client > maxSocket) { - maxSocket = client; - } - } - else { - char buffer[SYNAPSE_MESSAGE_SIZE_MAX] = {}; - Socket socket = { connectionSock, {} }; - const int32_t size = recv_message(socket, buffer, 256); - if (size > 0) - { - processIncomingMessage(SerializedAxonMessage(buffer, size), socket); - } - else if (size < 0) - { - FD_CLR(connectionSock, &master); - CLOSESOCKET(connectionSock); - continue; - } - } - } - } - update(); - } -} - -template<> -inline void Networking::BasicSynapse::listen() -{ - SOCKADDR_IN_T host = {}; - - while (isAlive) { - char buffer[SYNAPSE_MESSAGE_SIZE_MAX] = {}; - int32_t size = recv_message(socketInfo, buffer, SYNAPSE_MESSAGE_SIZE_MAX); - if (size > 0) { - processIncomingMessage(SerializedAxonMessage(buffer, size), socketInfo); - } - - update(); - } -} - -#pragma endregion - -#pragma region CLIENT_FUNCTIONS - -template<> -inline void Networking::BasicSynapse::listen() { - // Todo: async support - SOCKADDR_IN_T host = socketInfo.conn; - SOCKET_T client = socketInfo.socket; - - while (isAlive) - { - char buffer[SYNAPSE_MESSAGE_SIZE_MAX] = {}; - const int32_t size = recv_tcp_message(reinterpret_cast(buffer), 256, client); - if (size > 0) - { - processIncomingMessage(SerializedAxonMessage(buffer, size), socketInfo); - } - - update(); - } -} - -template<> -inline void Networking::BasicSynapse::listen() { - SOCKADDR_IN_T host = {}; - - while (isAlive) { - char buffer[SYNAPSE_MESSAGE_SIZE_MAX] = {}; - int32_t size = recv_udp_message(reinterpret_cast (buffer), SYNAPSE_MESSAGE_SIZE_MAX, socketInfo.socket, - &host); - if (size > 0) { - processIncomingMessage(SerializedAxonMessage(buffer, size), socketInfo); - } - - update(); - } +template +void Networking::BasicSynapse::listen() { + controller->listen(); } #pragma endregion diff --git a/libraries/networking/synapse/Synapse.ipp b/libraries/networking/synapse/Synapse.ipp index b7f7e7d..166edcc 100644 --- a/libraries/networking/synapse/Synapse.ipp +++ b/libraries/networking/synapse/Synapse.ipp @@ -77,6 +77,7 @@ void Networking::AsyncSynapse::kill() return; this->isAlive = false; + this->controller->kill(); proc.join(); } @@ -90,6 +91,7 @@ template void Networking::AsyncSynapse::start() { this->isAlive = true; + this->controller->start(); proc = std::thread(&AsyncSynapse::listen, this); } diff --git a/libraries/networking/synapse/SynapseInterface.hpp b/libraries/networking/synapse/SynapseInterface.hpp new file mode 100644 index 0000000..6f4ed40 --- /dev/null +++ b/libraries/networking/synapse/SynapseInterface.hpp @@ -0,0 +1,31 @@ +#pragma once +#include +#include "networking/synapse/utils/SynapseUtility.hpp" +#include "networking/synapse/utils/SynapseEvents.hpp" + + +namespace Networking { + class AXON_DECLSPEC SynapseInterface { + public: + SynapseInterface() = default; + virtual ~SynapseInterface() = default; + + WGETTER ( bool alive() ) { return isAlive.load(); } + virtual void kill() { isAlive.store(false); } + + virtual void start() = 0; + virtual void send(AxonMessage &) = 0; + virtual void sendTo(AxonMessage&, const Socket&) = 0; + + EventSystem::AxonEventManager& getEventManager() { return events; } + virtual void listen() = 0; + virtual void update() = 0; + virtual void onMessageReceived(const AxonMessage&, const Socket&) = 0; + virtual void processIncomingMessage(const SerializedAxonMessage&, const Socket&) = 0; + protected: + std::atomic isAlive = false; + EventSystem::AxonEventManager events; + }; + + typedef SynapseInterface* SynapseInterfacePtr; +} \ No newline at end of file diff --git a/libraries/networking/synapse/netcontroller/AxonNetworkController.hpp b/libraries/networking/synapse/netcontroller/AxonNetworkController.hpp new file mode 100644 index 0000000..663fa23 --- /dev/null +++ b/libraries/networking/synapse/netcontroller/AxonNetworkController.hpp @@ -0,0 +1,55 @@ +#pragma once +#include + +#include + +#include +#include +#include + +namespace Networking { + typedef Socket NetworkNodeInfo; + + class AXON_DECLSPEC AxonNetworkControllerBase { + public: + virtual ~AxonNetworkControllerBase() = default; + + GETTER bool isAlive() { return alive; } + + virtual void start(); + void kill(); + + virtual void listen() = 0; + virtual void send(AxonMessage&) = 0; + virtual void sendTo(AxonMessage&, const NetworkNodeInfo&) = 0; + protected: + virtual void sendSerializedTo(const SerializedAxonMessage&, const NetworkNodeInfo&) = 0; + private: + std::atomic alive = false; + }; + + template + class AXON_DECLSPEC BerkeleyAxonNetworkController : public AxonNetworkControllerBase { + public: + BerkeleyAxonNetworkController() = delete; + + explicit BerkeleyAxonNetworkController(SynapseInterface * , uint32_t); + explicit BerkeleyAxonNetworkController(SynapseInterface * , ConnectionInfo); + + ~BerkeleyAxonNetworkController() override; + + void listen() override {}; + void send(AxonMessage&) override; + void sendTo(AxonMessage&, const NetworkNodeInfo&) override; + protected: + void sendSerializedTo(const SerializedAxonMessage&, const NetworkNodeInfo&) override; + private: + ConnectionInfo meta; + NetworkNodeInfo connection; // Client-only feature, server will store nothing + protected: + SynapseInterface *owningSynapse; + }; +} + + +#include "AxonNetworkController.ipp" diff --git a/libraries/networking/synapse/netcontroller/AxonNetworkController.ipp b/libraries/networking/synapse/netcontroller/AxonNetworkController.ipp new file mode 100644 index 0000000..37bfbb3 --- /dev/null +++ b/libraries/networking/synapse/netcontroller/AxonNetworkController.ipp @@ -0,0 +1,166 @@ +#pragma once +#include +#include + +namespace Networking { + void AxonNetworkControllerBase::start() { + this->alive = true; + } + + void AxonNetworkControllerBase::kill() { + this->alive = false; + } + + template + BerkeleyAxonNetworkController::BerkeleyAxonNetworkController(SynapseInterface *owner, uint32_t port) : + meta({ "", port }), + connection(), + owningSynapse(owner) + { + static_assert(mode == SynapseMode::SERVER); + if (uint8_t ret = initialize_server ( connection, port ); ret != SUCCESS) { + throw Networking::AxonNetworkingInternalError(ret); + } + } + + template + BerkeleyAxonNetworkController::BerkeleyAxonNetworkController(SynapseInterface *owner, const ConnectionInfo info) : + meta(info), + connection(), + owningSynapse(owner) + { + static_assert(mode == SynapseMode::CLIENT); + if (uint8_t ret = initialize_client ( connection, info.hostname.c_str(), info.port ); ret != SUCCESS) { + throw Networking::AxonNetworkingInternalError(ret); + } + } + + template + BerkeleyAxonNetworkController::~BerkeleyAxonNetworkController() { + this->kill(); + finalize(connection); + } + + template + void BerkeleyAxonNetworkController::send(AxonMessage &message) { + this->sendTo(message, this->connection); + } + + template + void BerkeleyAxonNetworkController::sendTo(AxonMessage &message, const NetworkNodeInfo &dest) { + this->sendSerializedTo(message.getSerialized(), dest); + } + + template + void BerkeleyAxonNetworkController::sendSerializedTo(const SerializedAxonMessage &serialized, + const NetworkNodeInfo &dest) { + send_message(dest, serialized.getBits(), serialized.getSize()); + } + + +#pragma region SERVER_FUNCTIONS + + template<> + inline void Networking::BerkeleyAxonNetworkController::listen() + { + fd_set master; + FD_ZERO(&master); + FD_SET(connection.socket, &master); + SOCKET_T maxSocket = connection.socket; + + while (this->isAlive()) + { + timeval tv = { 0, 10000 }; + fd_set reads = master; + if (select(maxSocket + 1, &reads, nullptr, nullptr, &tv) <= 0) { + continue; + } + for (SOCKET_T connectionSock = 1; connectionSock <= maxSocket; connectionSock++) { + if (FD_ISSET(connectionSock, &reads)){ + if (connectionSock == connection.socket) { + sockaddr_storage storage = {}; + SOCKET_T client = accept_incoming(connection.socket, reinterpret_cast(&storage)); + + if (!CHECK_VALID(client)) { + continue; + } + + FD_SET(client, &master); + if (client > maxSocket) { + maxSocket = client; + } + } + else { + char buffer[SYNAPSE_MESSAGE_SIZE_MAX] = {}; + Socket socket = { connectionSock, {} }; + const int32_t size = recv_message(socket, buffer, 256); + if (size > 0) + { + owningSynapse->processIncomingMessage(SerializedAxonMessage(buffer, size), socket); + } + else if (size < 0) + { + FD_CLR(connectionSock, &master); + CLOSESOCKET(connectionSock); + continue; + } + } + } + } + owningSynapse->update(); + } + } + + template<> + inline void Networking::BerkeleyAxonNetworkController::listen() + { + while (this->isAlive()) { + char buffer[SYNAPSE_MESSAGE_SIZE_MAX] = {}; + int32_t size = recv_message(connection, buffer, SYNAPSE_MESSAGE_SIZE_MAX); + if (size > 0) { + owningSynapse->processIncomingMessage(SerializedAxonMessage(buffer, size), connection); + } + + owningSynapse->update(); + } + } + +#pragma endregion + +#pragma region CLIENT_FUNCTIONS + + template<> + inline void Networking::BerkeleyAxonNetworkController::listen() { + SOCKET_T client = connection.socket; + + while (this->isAlive()) + { + char buffer[SYNAPSE_MESSAGE_SIZE_MAX] = {}; + const int32_t size = recv_tcp_message(reinterpret_cast(buffer), 256, client); + if (size > 0) + { + owningSynapse->processIncomingMessage(SerializedAxonMessage(buffer, size), connection); + } + + owningSynapse->update(); + } + } + + template<> + inline void Networking::BerkeleyAxonNetworkController::listen() { + SOCKADDR_IN_T host = {}; + + while (this->isAlive()) { + char buffer[SYNAPSE_MESSAGE_SIZE_MAX] = {}; + int32_t size = recv_udp_message(reinterpret_cast (buffer), SYNAPSE_MESSAGE_SIZE_MAX, connection.socket, + &host); + if (size > 0) { + owningSynapse->processIncomingMessage(SerializedAxonMessage(buffer, size), connection); + } + + owningSynapse->update(); + } + } + +#pragma endregion +} \ No newline at end of file From 8d64cda2c5bbd557715c190022103eadf0c3e5da Mon Sep 17 00:00:00 2001 From: KbrdDestroyer Date: Tue, 3 Jun 2025 15:22:23 +0300 Subject: [PATCH 27/47] Removed deprecates --- libraries/networking/synapse/BasicSynapse.hpp | 6 ++-- libraries/networking/synapse/BasicSynapse.ipp | 7 ---- libraries/networking/synapse/Synapse.ipp | 5 +-- .../networking/synapse/SynapseInterface.hpp | 32 ++++++++----------- 4 files changed, 18 insertions(+), 32 deletions(-) diff --git a/libraries/networking/synapse/BasicSynapse.hpp b/libraries/networking/synapse/BasicSynapse.hpp index 176a837..00a1722 100644 --- a/libraries/networking/synapse/BasicSynapse.hpp +++ b/libraries/networking/synapse/BasicSynapse.hpp @@ -41,6 +41,9 @@ namespace Networking { ~BasicSynapse() override; + GETTER bool alive() const { return this->controller->isAlive(); } + + void kill() override { this->controller->kill(); } void start() override; void send(AxonMessage&) override; void sendTo(AxonMessage&, const Socket&) override; @@ -52,9 +55,6 @@ namespace Networking { void processIncomingMessage(const SerializedAxonMessage&, const Socket&) override; protected: - ConnectionInfo connectionInfo; - Socket socketInfo; - std::unique_ptr> controller; }; } diff --git a/libraries/networking/synapse/BasicSynapse.ipp b/libraries/networking/synapse/BasicSynapse.ipp index 8c25fb6..b9265e7 100644 --- a/libraries/networking/synapse/BasicSynapse.ipp +++ b/libraries/networking/synapse/BasicSynapse.ipp @@ -6,24 +6,18 @@ template Networking::BasicSynapse::BasicSynapse(uint32_t port) : - connectionInfo({"", port}), - socketInfo(), controller(std::make_unique>(this, port)) {} template Networking::BasicSynapse::BasicSynapse(const ConnectionInfo& connection) : - connectionInfo(connection), - socketInfo(), controller(std::make_unique>(this, connection)) {} template Networking::BasicSynapse::~BasicSynapse() { - isAlive = false; controller->kill(); - finalize(socketInfo); } #pragma endregion @@ -31,7 +25,6 @@ Networking::BasicSynapse::~BasicSynapse() template void Networking::BasicSynapse::start() { - isAlive.store(true); controller->start(); listen(); } diff --git a/libraries/networking/synapse/Synapse.ipp b/libraries/networking/synapse/Synapse.ipp index 166edcc..d3ea6dc 100644 --- a/libraries/networking/synapse/Synapse.ipp +++ b/libraries/networking/synapse/Synapse.ipp @@ -51,7 +51,6 @@ void Networking::Synapse::onMessageReceived(const AxonMessage& messa if (!message.hasFlag(PARTIAL)) { - // Fini std::shared_ptr res = mmap->collapse(message.ID()); if (!res) return; @@ -73,10 +72,9 @@ void Networking::Synapse::onMessageReceived(const AxonMessage& messa template void Networking::AsyncSynapse::kill() { - if (!this->isAlive) + if (!this->controller->isAlive()) return; - this->isAlive = false; this->controller->kill(); proc.join(); } @@ -90,7 +88,6 @@ Networking::AsyncSynapse::~AsyncSynapse() template void Networking::AsyncSynapse::start() { - this->isAlive = true; this->controller->start(); proc = std::thread(&AsyncSynapse::listen, this); } diff --git a/libraries/networking/synapse/SynapseInterface.hpp b/libraries/networking/synapse/SynapseInterface.hpp index 6f4ed40..843cd95 100644 --- a/libraries/networking/synapse/SynapseInterface.hpp +++ b/libraries/networking/synapse/SynapseInterface.hpp @@ -6,26 +6,22 @@ namespace Networking { class AXON_DECLSPEC SynapseInterface { - public: - SynapseInterface() = default; - virtual ~SynapseInterface() = default; + public: + SynapseInterface() = default; + virtual ~SynapseInterface() = default; - WGETTER ( bool alive() ) { return isAlive.load(); } - virtual void kill() { isAlive.store(false); } + virtual void kill() = 0; - virtual void start() = 0; - virtual void send(AxonMessage &) = 0; - virtual void sendTo(AxonMessage&, const Socket&) = 0; + virtual void start() = 0; + virtual void send(AxonMessage &) = 0; + virtual void sendTo(AxonMessage&, const Socket&) = 0; - EventSystem::AxonEventManager& getEventManager() { return events; } - virtual void listen() = 0; - virtual void update() = 0; - virtual void onMessageReceived(const AxonMessage&, const Socket&) = 0; - virtual void processIncomingMessage(const SerializedAxonMessage&, const Socket&) = 0; - protected: - std::atomic isAlive = false; - EventSystem::AxonEventManager events; + EventSystem::AxonEventManager& getEventManager() { return events; } + virtual void listen() = 0; + virtual void update() = 0; + virtual void onMessageReceived(const AxonMessage&, const Socket&) = 0; + virtual void processIncomingMessage(const SerializedAxonMessage&, const Socket&) = 0; + protected: + EventSystem::AxonEventManager events; }; - - typedef SynapseInterface* SynapseInterfacePtr; } \ No newline at end of file From 8791f1b55b103f3cd4bed7d0a29cd5016167ed6b Mon Sep 17 00:00:00 2001 From: KbrdDestroyer Date: Tue, 3 Jun 2025 17:21:32 +0300 Subject: [PATCH 28/47] Added cxx standart to libnetworking --- libraries/networking/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/networking/CMakeLists.txt b/libraries/networking/CMakeLists.txt index 44a90a9..5a1cd27 100644 --- a/libraries/networking/CMakeLists.txt +++ b/libraries/networking/CMakeLists.txt @@ -1,4 +1,5 @@ -project ("AxonEngine.libraries.networking") +project ("AxonEngine.libraries.networking" LANGUAGES C CXX) +SET (CMAKE_CXX_STANDARD 17) file(GLOB_RECURSE SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.c" From 52c2a82a27371ab5f06679450c11554562eb27d0 Mon Sep 17 00:00:00 2001 From: KbrdDestroyer Date: Tue, 3 Jun 2025 17:54:04 +0300 Subject: [PATCH 29/47] Added common LIBD_DIR variable in CMake --- libraries/CMakeLists.txt | 1 + libraries/backends/CMakeLists.txt | 2 +- libraries/events/CMakeLists.txt | 3 +-- libraries/messages/CMakeLists.txt | 4 ++-- libraries/networking/CMakeLists.txt | 5 ++--- 5 files changed, 7 insertions(+), 8 deletions(-) diff --git a/libraries/CMakeLists.txt b/libraries/CMakeLists.txt index 5e2c8ef..d9e3ece 100644 --- a/libraries/CMakeLists.txt +++ b/libraries/CMakeLists.txt @@ -5,5 +5,6 @@ message(STATUS "Searching for build config in ${V_GLOB}") set (CMAKE_POSITION_INDEPENDENT_CODE ON) set (COMMON_SRC "AxonUtility.h" PARENT_SCOPE) +set (LIBS_DIR ${CMAKE_CURRENT_SOURCE_DIR}) add_all_subdirs() \ No newline at end of file diff --git a/libraries/backends/CMakeLists.txt b/libraries/backends/CMakeLists.txt index 119ac20..862874e 100644 --- a/libraries/backends/CMakeLists.txt +++ b/libraries/backends/CMakeLists.txt @@ -3,5 +3,5 @@ project ("AxonEngine.libraries.backends") file(GLOB_RECURSE SOURCES "*.c" "*.h" "*.cpp" "*.hpp") add_library(backends STATIC ${SOURCES}) -target_include_directories(backends PUBLIC "${CMAKE_HOME_DIRECTORY}/libraries") +target_include_directories(backends PUBLIC ${LIBS_DIR}) target_include_directories(backends PUBLIC "${CMAKE_HOME_DIRECTORY}/common") diff --git a/libraries/events/CMakeLists.txt b/libraries/events/CMakeLists.txt index fa4da64..f6c37d1 100644 --- a/libraries/events/CMakeLists.txt +++ b/libraries/events/CMakeLists.txt @@ -3,5 +3,4 @@ project ("AxonEngine.libraries.events") file(GLOB_RECURSE SOURCES "*.c" "*.h" "*.cpp" "*.hpp" "*.ipp") add_library(events STATIC ${SOURCES}) -set (LIB_HOME ${CMAKE_HOME_DIRECTORY}/libraries) -target_include_directories(events PUBLIC "${LIB_HOME}") +target_include_directories(events PUBLIC "${LIBS_DIR}") diff --git a/libraries/messages/CMakeLists.txt b/libraries/messages/CMakeLists.txt index 3c7aa34..d87e9f2 100644 --- a/libraries/messages/CMakeLists.txt +++ b/libraries/messages/CMakeLists.txt @@ -9,7 +9,7 @@ file(GLOB_RECURSE SOURCES ) add_library(messages STATIC ${SOURCES}) -set (LIB_HOME ${CMAKE_HOME_DIRECTORY}/libraries) + target_compile_definitions(messages PUBLIC AXON_LIB) target_link_libraries(messages events serialization backends) -target_include_directories(messages PUBLIC "${LIB_HOME}") +target_include_directories(messages PUBLIC "${LIBS_DIR}") diff --git a/libraries/networking/CMakeLists.txt b/libraries/networking/CMakeLists.txt index 5a1cd27..ba0aeec 100644 --- a/libraries/networking/CMakeLists.txt +++ b/libraries/networking/CMakeLists.txt @@ -10,10 +10,9 @@ file(GLOB_RECURSE SOURCES ) add_library(networking SHARED ${SOURCES}) -set (LIB_HOME ${CMAKE_HOME_DIRECTORY}/libraries) target_compile_definitions(networking PUBLIC AXON_LIB) target_link_libraries(networking events serialization backends messages) -target_include_directories(networking PUBLIC "${LIB_HOME}") -target_include_directories(networking PUBLIC "${LIB_HOME}/networking") +target_include_directories(networking PUBLIC "${LIBS_DIR}") +target_include_directories(networking PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}") From 92a70af1b345c3ff6009b67d704ac2d2fe9958b5 Mon Sep 17 00:00:00 2001 From: KbrdDestroyer Date: Tue, 3 Jun 2025 18:07:04 +0300 Subject: [PATCH 30/47] Windows build required -std=c++17, event if it's passed manually in cmake, so rolled back c++17 feature for now --- .../synapse/netcontroller/AxonNetworkController.ipp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libraries/networking/synapse/netcontroller/AxonNetworkController.ipp b/libraries/networking/synapse/netcontroller/AxonNetworkController.ipp index 37bfbb3..c8eb63f 100644 --- a/libraries/networking/synapse/netcontroller/AxonNetworkController.ipp +++ b/libraries/networking/synapse/netcontroller/AxonNetworkController.ipp @@ -18,7 +18,8 @@ namespace Networking { owningSynapse(owner) { static_assert(mode == SynapseMode::SERVER); - if (uint8_t ret = initialize_server ( connection, port ); ret != SUCCESS) { + uint8_t ret = initialize_server ( connection, port ); + if ( ret != SUCCESS ) { throw Networking::AxonNetworkingInternalError(ret); } } @@ -30,7 +31,8 @@ namespace Networking { owningSynapse(owner) { static_assert(mode == SynapseMode::CLIENT); - if (uint8_t ret = initialize_client ( connection, info.hostname.c_str(), info.port ); ret != SUCCESS) { + uint8_t ret = initialize_client ( connection, info.hostname.c_str(), info.port ); + if ( ret != SUCCESS ) { throw Networking::AxonNetworkingInternalError(ret); } } From a0e24b1ee2d6dfd2adf9c2321d3f7e37ee3bfded Mon Sep 17 00:00:00 2001 From: Keyboard Destroyer <43577127+kbrddestroyer@users.noreply.github.com> Date: Sat, 7 Jun 2025 13:40:14 +0300 Subject: [PATCH 31/47] dev/global/synapse_refactor (#127) Changed synapse behaviour, added FakeNetwork for test functionality --- examples/basics/basic-synapse/client.cpp | 4 +- examples/basics/basic-synapse/server.cpp | 4 +- libraries/AxonUtility.h | 4 ++ libraries/backends/CMakeLists.txt | 1 + libraries/events/CMakeLists.txt | 1 + libraries/networking/CMakeLists.txt | 7 ++- libraries/networking/synapse/BasicSynapse.hpp | 16 +++-- libraries/networking/synapse/BasicSynapse.ipp | 46 +++++++------- libraries/networking/synapse/Synapse.hpp | 24 ++++---- libraries/networking/synapse/Synapse.ipp | 40 ++++++------ .../netcontroller/AxonNetworkController.hpp | 16 +++-- .../netcontroller/AxonNetworkController.ipp | 14 +++-- .../networking/utility/AxonNetworkPointer.cpp | 5 -- .../networking/utility/AxonNetworkPointer.hpp | 41 ++++++++++++- .../networking/utility/AxonNetworkPointer.ipp | 38 ++++++++++++ tests/gtest/CMakeLists.txt | 3 +- .../FakeNetworkController.hpp | 61 +++++++++++++++++++ .../FakeNetworkController.ipp | 54 ++++++++++++++++ tests/gtest/test_synapse.cpp | 32 +++------- tests/performance/perf_synapse.cpp | 10 ++- tests/utils/testutils/CMakeLists.txt | 2 +- 21 files changed, 311 insertions(+), 112 deletions(-) delete mode 100644 libraries/networking/utility/AxonNetworkPointer.cpp create mode 100644 libraries/networking/utility/AxonNetworkPointer.ipp create mode 100644 tests/gtest/FakeNetworkController/FakeNetworkController.hpp create mode 100644 tests/gtest/FakeNetworkController/FakeNetworkController.ipp diff --git a/examples/basics/basic-synapse/client.cpp b/examples/basics/basic-synapse/client.cpp index d538111..2a295f3 100644 --- a/examples/basics/basic-synapse/client.cpp +++ b/examples/basics/basic-synapse/client.cpp @@ -36,7 +36,9 @@ int main() { Networking::ConnectionInfo connection = { "localhost", 10423 }; - Networking::AsyncSynapse clientConnection(connection); + Networking::AsyncSynapse< + Networking::BerkeleyAxonNetworkController + > clientConnection(connection); clientConnection.getEventManager().subscribe(onMessageReceived); clientConnection.start(); diff --git a/examples/basics/basic-synapse/server.cpp b/examples/basics/basic-synapse/server.cpp index 7772919..6b13282 100644 --- a/examples/basics/basic-synapse/server.cpp +++ b/examples/basics/basic-synapse/server.cpp @@ -31,7 +31,9 @@ void onMessageReceived(const Networking::SynapseMessageReceivedEvent& event) int main() { - Networking::Synapse serverConnection(10423); + Networking::Synapse< + Networking::BerkeleyAxonNetworkController + > serverConnection(10423); serverConnection.getEventManager().subscribe(onMessageReceived); std::cout << "Starting Synapse connection" << std::endl; diff --git a/libraries/AxonUtility.h b/libraries/AxonUtility.h index 2d793fb..3869fa7 100644 --- a/libraries/AxonUtility.h +++ b/libraries/AxonUtility.h @@ -12,7 +12,11 @@ #if defined(WINDOWS_PLATFORM) #define GETTER #if defined(AXON_LIB) +#if defined(AXON_STATIC) +#define AXON_DECLSPEC +#else #define AXON_DECLSPEC __declspec(dllexport) +#endif #else #define AXON_DECLSPEC __declspec(dllimport) #endif diff --git a/libraries/backends/CMakeLists.txt b/libraries/backends/CMakeLists.txt index 862874e..d166ae7 100644 --- a/libraries/backends/CMakeLists.txt +++ b/libraries/backends/CMakeLists.txt @@ -5,3 +5,4 @@ add_library(backends STATIC ${SOURCES}) target_include_directories(backends PUBLIC ${LIBS_DIR}) target_include_directories(backends PUBLIC "${CMAKE_HOME_DIRECTORY}/common") +target_compile_definitions(backends PUBLIC AXON_LIB) diff --git a/libraries/events/CMakeLists.txt b/libraries/events/CMakeLists.txt index f6c37d1..c60ecbf 100644 --- a/libraries/events/CMakeLists.txt +++ b/libraries/events/CMakeLists.txt @@ -4,3 +4,4 @@ file(GLOB_RECURSE SOURCES "*.c" "*.h" "*.cpp" "*.hpp" "*.ipp") add_library(events STATIC ${SOURCES}) target_include_directories(events PUBLIC "${LIBS_DIR}") +target_compile_definitions(events PUBLIC AXON_LIB) diff --git a/libraries/networking/CMakeLists.txt b/libraries/networking/CMakeLists.txt index ba0aeec..65aaad4 100644 --- a/libraries/networking/CMakeLists.txt +++ b/libraries/networking/CMakeLists.txt @@ -9,7 +9,12 @@ file(GLOB_RECURSE SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.ipp" ) -add_library(networking SHARED ${SOURCES}) +if (AXON_STATIC) + add_library(networking STATIC ${SOURCES}) + add_compile_definitions(AXON_STATIC) +else() + add_library(networking SHARED ${SOURCES}) +endif() target_compile_definitions(networking PUBLIC AXON_LIB) target_link_libraries(networking events serialization backends messages) diff --git a/libraries/networking/synapse/BasicSynapse.hpp b/libraries/networking/synapse/BasicSynapse.hpp index 00a1722..8f94d7e 100644 --- a/libraries/networking/synapse/BasicSynapse.hpp +++ b/libraries/networking/synapse/BasicSynapse.hpp @@ -12,7 +12,7 @@ #include "messages/AxonMessage.hpp" #include "networking/synapse/utils/SynapseEvents.hpp" #include "SynapseInterface.hpp" -#include +#include namespace Networking { @@ -20,12 +20,13 @@ namespace Networking { * Basic connection handler * Specifies one-to-one connection for client and one-to-many for server. * - * @tparam conn connection mode (TCP|UDP) - * @tparam mode synapse mode (CLIENT|SERVER) + * @tparam NetworkController derived from AxonNetworkControllerBase class */ - template + template class AXON_DECLSPEC BasicSynapse : public SynapseInterface { + static_assert(std::is_base_of()); + static_assert(!std::is_abstract()); public: /** Default creation is restricted */ BasicSynapse() = delete; @@ -41,21 +42,18 @@ namespace Networking { ~BasicSynapse() override; - GETTER bool alive() const { return this->controller->isAlive(); } - - void kill() override { this->controller->kill(); } + void kill() override { this->networkController->kill(); } void start() override; void send(AxonMessage&) override; void sendTo(AxonMessage&, const Socket&) override; - // This function should be instanced for each connection type void listen() override; void update() override {} void onMessageReceived(const AxonMessage&, const Socket&) override {}; void processIncomingMessage(const SerializedAxonMessage&, const Socket&) override; protected: - std::unique_ptr> controller; + std::unique_ptr networkController; }; } diff --git a/libraries/networking/synapse/BasicSynapse.ipp b/libraries/networking/synapse/BasicSynapse.ipp index b9265e7..339e978 100644 --- a/libraries/networking/synapse/BasicSynapse.ipp +++ b/libraries/networking/synapse/BasicSynapse.ipp @@ -4,51 +4,51 @@ #pragma region BASIC_SYNAPSE #pragma region CONTRUCTING -template -Networking::BasicSynapse::BasicSynapse(uint32_t port) : - controller(std::make_unique>(this, port)) +template +Networking::BasicSynapse::BasicSynapse(uint32_t port) : + networkController(std::make_unique(this, port)) {} -template -Networking::BasicSynapse::BasicSynapse(const ConnectionInfo& connection) : - controller(std::make_unique>(this, connection)) +template +Networking::BasicSynapse::BasicSynapse(const ConnectionInfo& connection) : + networkController(std::make_unique(this, connection)) {} -template -Networking::BasicSynapse::~BasicSynapse() +template +Networking::BasicSynapse::~BasicSynapse() { - controller->kill(); + networkController->kill(); } #pragma endregion -template -void Networking::BasicSynapse::start() +template +void Networking::BasicSynapse::start() { - controller->start(); + networkController->start(); listen(); } -template -void Networking::BasicSynapse::send(AxonMessage& message) +template +void Networking::BasicSynapse::send(AxonMessage& message) { - controller->send(message); + networkController->send(message); } -template -void Networking::BasicSynapse::sendTo(AxonMessage& message, const Socket& dest) +template +void Networking::BasicSynapse::sendTo(AxonMessage& message, const Socket& dest) { - controller->sendTo(message, dest); + networkController->sendTo(message, dest); } -template -void Networking::BasicSynapse::processIncomingMessage(const SerializedAxonMessage &message, const Socket& from) { +template +void Networking::BasicSynapse::processIncomingMessage(const SerializedAxonMessage &message, const Socket& from) { onMessageReceived(AxonMessage(message), from); } -template -void Networking::BasicSynapse::listen() { - controller->listen(); +template +void Networking::BasicSynapse::listen() { + networkController->listen(); } #pragma endregion diff --git a/libraries/networking/synapse/Synapse.hpp b/libraries/networking/synapse/Synapse.hpp index ad71187..b71770b 100644 --- a/libraries/networking/synapse/Synapse.hpp +++ b/libraries/networking/synapse/Synapse.hpp @@ -13,17 +13,16 @@ namespace Networking /** * Advanced connection handler with event system * - * @tparam conn connection mode (TCP|UDP) - * @tparam mode synapse mode (CLIENT|SERVER) + * @tparam controller derived from AxonNetworkControllerBase class */ - template - class AXON_DECLSPEC Synapse : public BasicSynapse { + template + class AXON_DECLSPEC Synapse : public BasicSynapse { public: #pragma region CONSTRUCTING /** Initializes Synapse in server mode */ - explicit Synapse(uint32_t port) : BasicSynapse(port) {} + explicit Synapse(uint32_t port) : BasicSynapse(port) {} /** Initialize Synapse in client mode */ - explicit Synapse(const ConnectionInfo &info) : BasicSynapse(info) {} + explicit Synapse(const ConnectionInfo &info) : BasicSynapse(info) {} ~Synapse() override = default; #pragma endregion @@ -34,6 +33,8 @@ namespace Networking void sendTo(AxonMessage&, const Socket&) override; void sendPooled(const AxonMessage&, const Socket &) const; + + GETTER bool alive() { return this->networkController->isAlive(); } #pragma endregion protected: std::vector pendingValidation; @@ -44,18 +45,17 @@ namespace Networking /** * Synapse with listen() function in separated thread. * - * @tparam conn connection mode (TCP|UDP) - * @tparam mode synapse mode (CLIENT|SERVER) + * @tparam controller derived from AxonNetworkControllerBase class */ - template - class AXON_DECLSPEC AsyncSynapse final : public Synapse + template + class AXON_DECLSPEC AsyncSynapse final : public Synapse { public: /** Initializes Synapse in server mode */ - explicit AsyncSynapse(uint32_t port) : Synapse(port) {} + explicit AsyncSynapse(uint32_t port) : Synapse(port) {} /** Initialize Synapse in client mode */ - explicit AsyncSynapse(const ConnectionInfo& info) : Synapse(info) {} + explicit AsyncSynapse(const ConnectionInfo &info) : Synapse(info) {} ~AsyncSynapse() override; diff --git a/libraries/networking/synapse/Synapse.ipp b/libraries/networking/synapse/Synapse.ipp index d3ea6dc..d079605 100644 --- a/libraries/networking/synapse/Synapse.ipp +++ b/libraries/networking/synapse/Synapse.ipp @@ -4,8 +4,8 @@ #pragma region SYNAPSE -template -void Networking::Synapse::update() { +template +void Networking::Synapse::update() { MessagePoolNodePtr pNode = pool->pop(); if (!pNode.get()) return; @@ -13,8 +13,8 @@ void Networking::Synapse::update() { this->sendTo(pNode->message, pNode->destination); } -template -void Networking::Synapse::sendTo(AxonMessage &message, const Socket &dest) { +template +void Networking::Synapse::sendTo(AxonMessage &message, const Socket &dest) { const AxonMessage::UniqueAxonMessagePtr ptr = message.split(SYNAPSE_PAYLOAD_SIZE_MAX); if (ptr) { @@ -26,16 +26,16 @@ void Networking::Synapse::sendTo(AxonMessage &message, const Socket pendingValidation.push_back(message.ID()); } - BasicSynapse::sendTo(message, dest); + BasicSynapse::sendTo(message, dest); } -template -void Networking::Synapse::sendPooled(const AxonMessage& message, const Socket &dest) const { +template +void Networking::Synapse::sendPooled(const AxonMessage& message, const Socket &dest) const { pool->push( { message, dest } ); } -template -void Networking::Synapse::onMessageReceived(const AxonMessage& message, const Socket &from) +template +void Networking::Synapse::onMessageReceived(const AxonMessage& message, const Socket &from) { if (message.hasFlag(VALIDATE)) { @@ -43,7 +43,9 @@ void Networking::Synapse::onMessageReceived(const AxonMessage& messa } if (message.hasFlag(ACKNOWLEDGE) && !message.hasFlag(PARTIAL)) { - pendingValidation.erase(std::find(pendingValidation.begin(), pendingValidation.end(), message.ID())); + auto it = std::find(pendingValidation.begin(), pendingValidation.end(), message.ID()); + if (it != pendingValidation.end()) + pendingValidation.erase(it); } if (mmap->contains(message.ID()) || message.hasFlag(PARTIAL)) { @@ -69,26 +71,26 @@ void Networking::Synapse::onMessageReceived(const AxonMessage& messa #pragma region ASYNC_SYNAPSE -template -void Networking::AsyncSynapse::kill() +template +void Networking::AsyncSynapse::kill() { - if (!this->controller->isAlive()) + if (!this->networkController->isAlive()) return; - this->controller->kill(); + this->networkController->kill(); proc.join(); } -template -Networking::AsyncSynapse::~AsyncSynapse() +template +Networking::AsyncSynapse::~AsyncSynapse() { kill(); } -template -void Networking::AsyncSynapse::start() +template +void Networking::AsyncSynapse::start() { - this->controller->start(); + this->networkController->start(); proc = std::thread(&AsyncSynapse::listen, this); } diff --git a/libraries/networking/synapse/netcontroller/AxonNetworkController.hpp b/libraries/networking/synapse/netcontroller/AxonNetworkController.hpp index 663fa23..64b2332 100644 --- a/libraries/networking/synapse/netcontroller/AxonNetworkController.hpp +++ b/libraries/networking/synapse/netcontroller/AxonNetworkController.hpp @@ -1,20 +1,24 @@ #pragma once #include -#include +#include #include #include -#include +#include namespace Networking { typedef Socket NetworkNodeInfo; class AXON_DECLSPEC AxonNetworkControllerBase { public: - virtual ~AxonNetworkControllerBase() = default; + AxonNetworkControllerBase() = delete; - GETTER bool isAlive() { return alive; } + explicit AxonNetworkControllerBase(SynapseInterface *); + + virtual ~AxonNetworkControllerBase() { kill(); }; + + GETTER bool isAlive() { return alive.load(); } virtual void start(); void kill(); @@ -26,6 +30,8 @@ namespace Networking { virtual void sendSerializedTo(const SerializedAxonMessage&, const NetworkNodeInfo&) = 0; private: std::atomic alive = false; + protected: + SynapseInterface *owningSynapse; }; template @@ -46,8 +52,6 @@ namespace Networking { private: ConnectionInfo meta; NetworkNodeInfo connection; // Client-only feature, server will store nothing - protected: - SynapseInterface *owningSynapse; }; } diff --git a/libraries/networking/synapse/netcontroller/AxonNetworkController.ipp b/libraries/networking/synapse/netcontroller/AxonNetworkController.ipp index c8eb63f..4bb95ec 100644 --- a/libraries/networking/synapse/netcontroller/AxonNetworkController.ipp +++ b/libraries/networking/synapse/netcontroller/AxonNetworkController.ipp @@ -1,21 +1,25 @@ #pragma once #include -#include +#include + namespace Networking { void AxonNetworkControllerBase::start() { - this->alive = true; + this->alive.store(true); } void AxonNetworkControllerBase::kill() { - this->alive = false; + this->alive.store(false); } + AxonNetworkControllerBase::AxonNetworkControllerBase(SynapseInterface *owner) : + owningSynapse(owner) {} + template BerkeleyAxonNetworkController::BerkeleyAxonNetworkController(SynapseInterface *owner, uint32_t port) : meta({ "", port }), connection(), - owningSynapse(owner) + AxonNetworkControllerBase(owner) { static_assert(mode == SynapseMode::SERVER); uint8_t ret = initialize_server ( connection, port ); @@ -28,7 +32,7 @@ namespace Networking { BerkeleyAxonNetworkController::BerkeleyAxonNetworkController(SynapseInterface *owner, const ConnectionInfo info) : meta(info), connection(), - owningSynapse(owner) + AxonNetworkControllerBase(owner) { static_assert(mode == SynapseMode::CLIENT); uint8_t ret = initialize_client ( connection, info.hostname.c_str(), info.port ); diff --git a/libraries/networking/utility/AxonNetworkPointer.cpp b/libraries/networking/utility/AxonNetworkPointer.cpp deleted file mode 100644 index fa28cf0..0000000 --- a/libraries/networking/utility/AxonNetworkPointer.cpp +++ /dev/null @@ -1,5 +0,0 @@ -#include "AxonNetworkPointer.hpp" - -namespace Networking { - -} // Networking \ No newline at end of file diff --git a/libraries/networking/utility/AxonNetworkPointer.hpp b/libraries/networking/utility/AxonNetworkPointer.hpp index 97b34be..37bb766 100644 --- a/libraries/networking/utility/AxonNetworkPointer.hpp +++ b/libraries/networking/utility/AxonNetworkPointer.hpp @@ -1,8 +1,45 @@ #pragma once -#include "networking/synapse/utils/SynapseEvents.hpp" +#include +#include +#include +#include +#include namespace Networking { + template + class AXON_DECLSPEC AxonNetworkPtr { + static_assert(!std::is_abstract::value); + static_assert( + !std::is_trivially_copyable_v(), + "Type must be trivially copyable to be compatible with Axon Network Pointer"); + public: + AxonNetworkPtr() = delete; -} // Networking + virtual ~AxonNetworkPtr() = default; + GETTER T *get() const { return ptr; } + + void set(T); + + T &operator*() const; + + T *operator->() const; + + protected: + virtual void onValueChanged(); + + virtual void dispatchValueChangeEvent(); + + AxonMessage toMessage() const; + + private: + T *ptr = nullptr; + uint8_t flags = 0; + SynapseInterface *synapse = nullptr; + Socket connected = {}; + EventSystem::AxonEventManager events; + }; +} + +#include "AxonNetworkPointer.ipp" diff --git a/libraries/networking/utility/AxonNetworkPointer.ipp b/libraries/networking/utility/AxonNetworkPointer.ipp new file mode 100644 index 0000000..e4cfe4f --- /dev/null +++ b/libraries/networking/utility/AxonNetworkPointer.ipp @@ -0,0 +1,38 @@ +#pragma once +#include "AxonNetworkPointer.hpp" + +namespace Networking { + template + void AxonNetworkPtr::set(T val) { + *ptr = val; + + dispatchValueChangeEvent(); + } + + template + T &AxonNetworkPtr::operator*() const { + return *ptr; + } + + template + T *AxonNetworkPtr::operator->() const { + return ptr; + } + + template + void AxonNetworkPtr::onValueChanged() { + + } + + template + void AxonNetworkPtr::dispatchValueChangeEvent() { + synapse->sendTo(this->toMessage(), connected); + } + + template + AxonMessage AxonNetworkPtr::toMessage() const { + return AxonMessage( + ptr, sizeof( * ptr ), 0, flags + ); + } +} // Networking \ No newline at end of file diff --git a/tests/gtest/CMakeLists.txt b/tests/gtest/CMakeLists.txt index 90f6a04..a5ae41c 100644 --- a/tests/gtest/CMakeLists.txt +++ b/tests/gtest/CMakeLists.txt @@ -4,6 +4,7 @@ project ("AxonEngine.tests.gtest") find_package(GTest REQUIRED) enable_testing() -set (LIST_LIBRARIES networking GTest::gtest GTest::gtest_main) +set (LIST_LIBRARIES GTest::gtest GTest::gtest_main networking) list_all_tests("test_*.cpp" ${LIST_LIBRARIES}) include_directories("../../libraries") +include_directories("../utils/testutils") \ No newline at end of file diff --git a/tests/gtest/FakeNetworkController/FakeNetworkController.hpp b/tests/gtest/FakeNetworkController/FakeNetworkController.hpp new file mode 100644 index 0000000..a468aff --- /dev/null +++ b/tests/gtest/FakeNetworkController/FakeNetworkController.hpp @@ -0,0 +1,61 @@ +#pragma once +#include +#include +#include +#include +#include + +namespace Networking { + class AxonNetworkControllerBase; +} + +namespace TestUtils { + class FakeNetworkController; + + class FakeNetwork { + FakeNetwork() = default; + public: + static FakeNetwork & Instance () { + static FakeNetwork gInstance; + return gInstance; + } + + uint32_t create(const std::string &, uint32_t); + uint32_t connect(const std::string &, uint32_t); + + void bind(uint32_t, FakeNetworkController *); + + void sendto(const Networking::SerializedAxonMessage&, uint32_t, uint32_t); + private: + static uint32_t getDesc() { + static uint32_t desc = 0; + return ++desc; + } + private: + std::map pool = {}; + std::map> nodes = {}; + }; + + class FakeNetworkController : public Networking::AxonNetworkControllerBase { + public: + FakeNetworkController() = delete; + + explicit FakeNetworkController(Networking::SynapseInterface * owner, uint32_t); + explicit FakeNetworkController(Networking::SynapseInterface * owner, const Networking::ConnectionInfo&); + + void listen() override; + void send(Networking::AxonMessage&) override; + void sendTo(Networking::AxonMessage&, const Networking::NetworkNodeInfo&) override; + + + GETTER Networking::SynapseInterface * owner() { return owningSynapse; } + protected: + void sendSerializedTo(const Networking::SerializedAxonMessage&, const Networking::NetworkNodeInfo&) override; + + uint32_t connectedNode; + uint32_t self; + FakeNetwork &instance; + }; +} + +#include "FakeNetworkController.ipp" diff --git a/tests/gtest/FakeNetworkController/FakeNetworkController.ipp b/tests/gtest/FakeNetworkController/FakeNetworkController.ipp new file mode 100644 index 0000000..fd612cd --- /dev/null +++ b/tests/gtest/FakeNetworkController/FakeNetworkController.ipp @@ -0,0 +1,54 @@ +#pragma once + +inline void TestUtils::FakeNetwork::sendto(const Networking::SerializedAxonMessage &serialized, uint32_t socket, uint32_t from) { + pool[socket]->owner()->processIncomingMessage(serialized, { static_cast( socket ), {} }); +} + +inline uint32_t TestUtils::FakeNetwork::create( + const std::string &hostname, + uint32_t port + ) { + uint32_t desc = getDesc(); + this->nodes[hostname][port] = desc; + return desc; +} + +inline uint32_t TestUtils::FakeNetwork::connect(const std::string &hostname, uint32_t port) { + return this->nodes[hostname][port]; +} + +void TestUtils::FakeNetwork::bind(uint32_t desc, TestUtils::FakeNetworkController *controller) { + pool[desc] = controller; +} + +inline void TestUtils::FakeNetworkController::listen() {} + +inline void TestUtils::FakeNetworkController::send(Networking::AxonMessage &message) { + this->sendTo(message, {static_cast(connectedNode), {}}); +} + +inline void TestUtils::FakeNetworkController::sendTo(Networking::AxonMessage &message, const Networking::NetworkNodeInfo &node) { + this->sendSerializedTo(message.getSerialized(), node); +} + +inline void TestUtils::FakeNetworkController::sendSerializedTo(const Networking::SerializedAxonMessage &serialized, + const Networking::NetworkNodeInfo &node) { + instance.sendto(serialized, node.socket, self); +} + +inline TestUtils::FakeNetworkController::FakeNetworkController(Networking::SynapseInterface *owner, uint32_t port) : + AxonNetworkControllerBase(owner), + instance(FakeNetwork::Instance()) + { + connectedNode = self = instance.create("test-nodes-fake-host", port); + instance.bind(connectedNode, this); + } + +inline TestUtils::FakeNetworkController::FakeNetworkController(Networking::SynapseInterface *owner, + const Networking::ConnectionInfo &info) : + AxonNetworkControllerBase(owner), + instance(FakeNetwork::Instance()) { + self = instance.create("test-nodes-fake-clients", info.port); + connectedNode = instance.connect(info.hostname, info.port); + instance.bind(self, this); +} diff --git a/tests/gtest/test_synapse.cpp b/tests/gtest/test_synapse.cpp index 1cfd119..6ccc5f5 100644 --- a/tests/gtest/test_synapse.cpp +++ b/tests/gtest/test_synapse.cpp @@ -1,5 +1,7 @@ #include #include +#include "FakeNetworkController/FakeNetworkController.hpp" +#include bool hasVisited = false; @@ -8,10 +10,13 @@ void onMessageReceived(const Networking::SynapseMessageReceivedEvent& event) { hasVisited = true; } - -TEST(TEST_SYNAPSE, TEST_SYNAPSE_COMMON_UDP) { - Networking::AsyncSynapse server(10435); - Networking::AsyncSynapse client({"localhost", 10435}); +TEST(TEST_SYNAPSE, TEST_FAKE_NETWORK) { + Networking::Synapse< + TestUtils::FakeNetworkController + > server(10435); + Networking::Synapse< + TestUtils::FakeNetworkController + > client({"test-nodes-fake-host", 10435}); server.getEventManager().subscribe(onMessageReceived); server.start(); @@ -19,29 +24,10 @@ TEST(TEST_SYNAPSE, TEST_SYNAPSE_COMMON_UDP) { Networking::AxonMessage msg("Hello World!", sizeof("Hello World!")); client.send(msg); - - std::this_thread::sleep_for(std::chrono::seconds(1)); ASSERT_TRUE(hasVisited); - hasVisited = false; } -TEST(TEST_SYNAPSE, TEST_SYNAPSE_COMMON_TCP) { - Networking::AsyncSynapse server(10435); - Networking::AsyncSynapse client({"localhost", 10435}); - - server.getEventManager().subscribe(onMessageReceived); - server.start(); - client.start(); - Networking::AxonMessage msg("Hello World!", sizeof("Hello World!"), 2, 0); - - for (uint8_t i = 0; i < 3; i++) - client.send(msg); - - std::this_thread::sleep_for(std::chrono::seconds(5)); - ASSERT_TRUE(hasVisited); -} - int main(int argc, char* argv[]) { ::testing::InitGoogleTest(&argc, argv); diff --git a/tests/performance/perf_synapse.cpp b/tests/performance/perf_synapse.cpp index 3c1190d..1d0396c 100644 --- a/tests/performance/perf_synapse.cpp +++ b/tests/performance/perf_synapse.cpp @@ -4,14 +4,18 @@ #include int main() { - Networking::AsyncSynapse server(10432); - Networking::AsyncSynapse client({"localhost", 10432}); + Networking::AsyncSynapse< + Networking::BerkeleyAxonNetworkController + > server(10432); + Networking::AsyncSynapse< + Networking::BerkeleyAxonNetworkController + > client({"localhost", 10432}); server.start(); client.start(); ENABLE_MEMGUARD - for (uint8_t i = 0; i < 0; i++) + for (uint8_t i = 0; i < 4; i++) { DISABLE_MEMGUARD std::this_thread::sleep_for(std::chrono::milliseconds (100)); diff --git a/tests/utils/testutils/CMakeLists.txt b/tests/utils/testutils/CMakeLists.txt index 3bd04bc..1a4b506 100644 --- a/tests/utils/testutils/CMakeLists.txt +++ b/tests/utils/testutils/CMakeLists.txt @@ -9,4 +9,4 @@ file(GLOB_RECURSE SOURCES add_library(testutils STATIC ${SOURCES}) set (LIB_HOME ${CMAKE_HOME_DIRECTORY}/test/utils/testutils) -target_include_directories(networking PUBLIC "${LIB_HOME}") +target_include_directories(testutils PUBLIC "${LIB_HOME}") From 531aa45dfebee20a56a782bfdcb5bfb3c76bc7ae Mon Sep 17 00:00:00 2001 From: Keyboard Destroyer <43577127+kbrddestroyer@users.noreply.github.com> Date: Mon, 9 Jun 2025 00:02:18 +0300 Subject: [PATCH 32/47] =?UTF-8?q?Refactored=20headers,=20added=20inlines,?= =?UTF-8?q?=20moved=20all=20gtests=20under=20common=20entr=E2=80=A6=20(#12?= =?UTF-8?q?8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Refactored headers, added inlines, moved all gtests under common entry point and created separate CMake function for automatic tests resolution * Stole message processing functionality from Synapse and moved it to MessageProcessor class * Fixed FakeNetwork event dispatching, added serverID resolution to NetworkPointer. Added related unit tests * Added network object class, that is capable of serverID resolution * Add include * Added temp var --- cmake/build-utils.cmake | 19 ++++- examples/basics/basic-synapse/client.cpp | 2 +- examples/basics/basic-synapse/server.cpp | 2 +- libraries/AxonUtility.h | 4 +- libraries/events/AxonEvent.ipp | 3 +- libraries/messages/AxonMessage.hpp | 9 ++- libraries/networking/AxonLibrary.hpp | 12 +++ libraries/networking/AxonNetwork.hpp | 22 ++++-- libraries/networking/AxonNetwork.ipp | 0 libraries/networking/AxonNetworkObject.cpp | 39 ++++++++++ libraries/networking/AxonNetworkObject.hpp | 24 ++++++ libraries/networking/synapse/BasicSynapse.ipp | 3 +- libraries/networking/synapse/Synapse.hpp | 8 +- libraries/networking/synapse/Synapse.ipp | 35 +-------- .../netcontroller/AxonNetworkController.ipp | 23 +++--- .../synapse/utils/SynapseEvents.hpp | 2 +- .../networking/utility/AxonNetworkPointer.hpp | 19 ++--- .../networking/utility/AxonNetworkPointer.ipp | 17 +++- .../networking/utility/MessageProcessor.cpp | 55 +++++++++++++ .../networking/utility/MessageProcessor.hpp | 49 ++++++++++++ tests/basic_checks/CMakeLists.txt | 9 --- tests/basic_checks/test_event_system.cxx | 52 ------------- .../FakeNetworkController.hpp | 4 +- .../FakeNetworkController.ipp | 4 +- tests/gtest/entry.cpp | 8 ++ tests/gtest/test_data_buffer.cpp | 8 +- tests/gtest/test_event_system.cpp | 77 +++++++++++++++++++ tests/gtest/test_message_pool.cpp | 9 +-- tests/gtest/test_network_pointer.cpp | 16 ++++ tests/gtest/test_networking.cpp | 6 -- tests/gtest/test_serialization.cpp | 6 -- tests/gtest/test_synapse.cpp | 41 ++++++++-- tests/performance/CMakeLists.txt | 2 +- tests/performance/perf_synapse.cpp | 2 +- 34 files changed, 407 insertions(+), 184 deletions(-) create mode 100644 libraries/networking/AxonLibrary.hpp create mode 100644 libraries/networking/AxonNetwork.ipp create mode 100644 libraries/networking/AxonNetworkObject.cpp create mode 100644 libraries/networking/AxonNetworkObject.hpp create mode 100644 libraries/networking/utility/MessageProcessor.cpp create mode 100644 libraries/networking/utility/MessageProcessor.hpp delete mode 100644 tests/basic_checks/CMakeLists.txt delete mode 100644 tests/basic_checks/test_event_system.cxx create mode 100644 tests/gtest/entry.cpp create mode 100644 tests/gtest/test_event_system.cpp create mode 100644 tests/gtest/test_network_pointer.cpp diff --git a/cmake/build-utils.cmake b/cmake/build-utils.cmake index b4104e7..67222fb 100644 --- a/cmake/build-utils.cmake +++ b/cmake/build-utils.cmake @@ -10,7 +10,7 @@ function(add_all_subdirs) endforeach() endfunction() -function(list_all_tests name_pattern) +function(list_all_tests_separate name_pattern) file (GLOB_RECURSE TEST_SOURCES ${name_pattern}) foreach (TEST_SRC ${TEST_SOURCES}) @@ -31,3 +31,20 @@ function(list_all_tests name_pattern) message ("Loaded test sequence: ${FILENAME}") endforeach () endfunction() + +function(list_all_tests name_pattern) + file (GLOB_RECURSE TEST_SOURCES ${name_pattern}) + get_filename_component(FOLDER ${CMAKE_CURRENT_SOURCE_DIR} NAME_WE) + string (TOUPPER ${FOLDER} FOLDER) + + add_executable(TEST_${FOLDER}_TARGET ${TEST_SOURCES} "entry.cpp") + add_test(NAME TEST_${FOLDER} COMMAND $) + target_link_libraries(TEST_${FOLDER}_TARGET PRIVATE ${ARGN}) + + add_custom_command(TARGET TEST_${FOLDER}_TARGET POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy -t $ $ + COMMAND_EXPAND_LISTS + ) + + message ("Loaded test folder: TEST_${FOLDER}") +endfunction() \ No newline at end of file diff --git a/examples/basics/basic-synapse/client.cpp b/examples/basics/basic-synapse/client.cpp index 2a295f3..e51effe 100644 --- a/examples/basics/basic-synapse/client.cpp +++ b/examples/basics/basic-synapse/client.cpp @@ -6,7 +6,7 @@ * server messages handling, displaying response packages. */ -#include +#include #include #include diff --git a/examples/basics/basic-synapse/server.cpp b/examples/basics/basic-synapse/server.cpp index 6b13282..bcfd370 100644 --- a/examples/basics/basic-synapse/server.cpp +++ b/examples/basics/basic-synapse/server.cpp @@ -5,7 +5,7 @@ * This file shows basic server logic and message handling using asynchronous Synapse with event system. */ -#include +#include #include #include diff --git a/libraries/AxonUtility.h b/libraries/AxonUtility.h index 3869fa7..a75497f 100644 --- a/libraries/AxonUtility.h +++ b/libraries/AxonUtility.h @@ -3,14 +3,13 @@ #include -#if defined(MSVC) || defined(__GNUC__) || defined(__clang__) +#if defined(MSVC) || defined(__GNUC__) || defined(__clang__) || defined(WINDOWS_PLATFORM) #define GETTER [[nodiscard("Ignoring getter return value is not allowed. For god's sake, have some respect!")]] #else #define GETTER #endif #if defined(WINDOWS_PLATFORM) -#define GETTER #if defined(AXON_LIB) #if defined(AXON_STATIC) #define AXON_DECLSPEC @@ -34,3 +33,4 @@ #define WGETTER GETTER_WNE #endif + diff --git a/libraries/events/AxonEvent.ipp b/libraries/events/AxonEvent.ipp index c0e0bf2..93e7625 100644 --- a/libraries/events/AxonEvent.ipp +++ b/libraries/events/AxonEvent.ipp @@ -18,8 +18,7 @@ void EventSystem::AxonEventManager::subscribe(std::function call template void EventSystem::AxonEventManager::subscribe(void(C::* callback)(const T&), C* instance) { - std::type_index type = std::type_index(typeid(T)); - + const auto type = std::type_index(typeid(T)); subscribers[type].push_back( [callback, instance](AxonEvent* base_event) { if (T* event = dynamic_cast(base_event)) diff --git a/libraries/messages/AxonMessage.hpp b/libraries/messages/AxonMessage.hpp index 6b7254b..824566a 100644 --- a/libraries/messages/AxonMessage.hpp +++ b/libraries/messages/AxonMessage.hpp @@ -28,10 +28,15 @@ namespace Networking VALIDATE = 1, ///< "how copy?" ACKNOWLEDGE = 1 << 1, ///< response package, "copy that!" PARTIAL = 1 << 2, ///< set if message bits are part of a partial delivery - ALL = UNDEFINED | VALIDATE | ACKNOWLEDGE | PARTIAL + NETOBJ_INI = 1 << 3, + NETOBJ_REPL = 1 << 4, + TO_ALL = 1 << 5, + SERV_STORE = 1 << 6, + + ALL = UNDEFINED | VALIDATE | ACKNOWLEDGE | PARTIAL | NETOBJ_INI | NETOBJ_REPL | TO_ALL | SERV_STORE }; - static_assert(ALL == 0b111, "Flag set is incorrect. Check ALL value or manually edit this assert"); + static_assert(ALL == 0b1111111, "Flag set is incorrect. Check ALL value or manually edit this assert"); class AxonMessage; /** diff --git a/libraries/networking/AxonLibrary.hpp b/libraries/networking/AxonLibrary.hpp new file mode 100644 index 0000000..31e2bff --- /dev/null +++ b/libraries/networking/AxonLibrary.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include "messages/AxonBinaryStream.hpp" +#include "networking/synapse/utils/SynapseEvents.hpp" +#include "networking/synapse/utils/SynapseUtility.hpp" +#include +#include +#include +#include "networking/synapse/utils/SynapseEvents.hpp" +#include + +#include diff --git a/libraries/networking/AxonNetwork.hpp b/libraries/networking/AxonNetwork.hpp index cda2d9e..637d059 100644 --- a/libraries/networking/AxonNetwork.hpp +++ b/libraries/networking/AxonNetwork.hpp @@ -1,19 +1,25 @@ #pragma once -#include "messages/AxonBinaryStream.hpp" -#include "networking/synapse/utils/SynapseEvents.hpp" -#include "networking/synapse/utils/SynapseUtility.hpp" -#include -#include -#include -#include "networking/synapse/utils/SynapseEvents.hpp" -#include +#include +#include + +#include namespace Networking { class AXON_DECLSPEC AxonNetworkManager { + public: + AxonNetworkManager() = default; + + template + void initialize(); + virtual uint64_t getUniqueIDInNetwork() = 0; + private: + std::unique_ptr synapse; }; } +#include "AxonNetwork.ipp" + /* AxonNetwork.hpp */ diff --git a/libraries/networking/AxonNetwork.ipp b/libraries/networking/AxonNetwork.ipp new file mode 100644 index 0000000..e69de29 diff --git a/libraries/networking/AxonNetworkObject.cpp b/libraries/networking/AxonNetworkObject.cpp new file mode 100644 index 0000000..feb8c09 --- /dev/null +++ b/libraries/networking/AxonNetworkObject.cpp @@ -0,0 +1,39 @@ +#include "AxonNetworkObject.hpp" +#include + + + +Networking::AxonNetworkObject::AxonNetworkObject(SynapseInterface * synapse) : + synapse(synapse) { + if (synapse) { + + synapse->getEventManager().subscribe< + AxonNetworkObject, SynapseMessageReceivedEvent + >(&AxonNetworkObject::onIDResolved, this); + resolveNetworkID(); + } +} + +void Networking::AxonNetworkObject::resolveNetworkID() { + this->clientID = MessageProcessor::RequestUniqueIDProto::generateID(); + + MessageProcessor::RequestUniqueIDProto request = { + clientID, 0 + }; + + AxonMessage msg(&request, sizeof(request), 0, NETOBJ_INI); + synapse->send(msg); +} + +void Networking::AxonNetworkObject::onIDResolved(const SynapseMessageReceivedEvent &event) { + const AxonMessage & message = event.getMessage(); + + if (!message.hasFlag(NETOBJ_REPL)) return; + + MessageProcessor::RequestUniqueIDProto repl = * static_cast < MessageProcessor::RequestUniqueIDProto * >( message.getMessage() ); + if (repl.clientSideID != this->clientID) return; + + this->serverID = repl.serverSideID; +} + + diff --git a/libraries/networking/AxonNetworkObject.hpp b/libraries/networking/AxonNetworkObject.hpp new file mode 100644 index 0000000..b75fef0 --- /dev/null +++ b/libraries/networking/AxonNetworkObject.hpp @@ -0,0 +1,24 @@ +#pragma once +#include +#include + + +namespace Networking { + class AXON_DECLSPEC AxonNetworkObject { + public: + AxonNetworkObject() = delete; + AxonNetworkObject( SynapseInterface * ); + virtual ~AxonNetworkObject() = default; + + WGETTER ( bool ready() ) { return serverID != 0; } + WGETTER( uint64_t id() ) { return serverID; } + protected: + void resolveNetworkID(); + void onIDResolved(const SynapseMessageReceivedEvent&); + private: + uint64_t serverID = 0; + uint32_t clientID = 0; + protected: + SynapseInterface * synapse = nullptr; + }; +} diff --git a/libraries/networking/synapse/BasicSynapse.ipp b/libraries/networking/synapse/BasicSynapse.ipp index 339e978..d23ad63 100644 --- a/libraries/networking/synapse/BasicSynapse.ipp +++ b/libraries/networking/synapse/BasicSynapse.ipp @@ -51,5 +51,4 @@ void Networking::BasicSynapse::listen() { networkController->listen(); } -#pragma endregion -#pragma endregion +#pragma endregion \ No newline at end of file diff --git a/libraries/networking/synapse/Synapse.hpp b/libraries/networking/synapse/Synapse.hpp index b71770b..068a8d4 100644 --- a/libraries/networking/synapse/Synapse.hpp +++ b/libraries/networking/synapse/Synapse.hpp @@ -7,6 +7,7 @@ #include "messages/AxonMessage.hpp" #include "networking/synapse/utils/SynapseUtility.hpp" +#include namespace Networking { @@ -37,10 +38,9 @@ namespace Networking GETTER bool alive() { return this->networkController->isAlive(); } #pragma endregion protected: - std::vector pendingValidation; - std::unique_ptr pool = std::make_unique(); - std::unique_ptr mmap = std::make_unique(); - }; + ADD_MODULE(MessageProcessor, msgproc, this); + friend MessageProcessor; + }; /** * Synapse with listen() function in separated thread. diff --git a/libraries/networking/synapse/Synapse.ipp b/libraries/networking/synapse/Synapse.ipp index d079605..8dd9250 100644 --- a/libraries/networking/synapse/Synapse.ipp +++ b/libraries/networking/synapse/Synapse.ipp @@ -6,7 +6,7 @@ template void Networking::Synapse::update() { - MessagePoolNodePtr pNode = pool->pop(); + MessagePoolNodePtr pNode = this->msgproc->processPool(); if (!pNode.get()) return; @@ -23,7 +23,7 @@ void Networking::Synapse::sendTo(AxonMessage &message, const Socket if (message.hasFlag(VALIDATE)) { - pendingValidation.push_back(message.ID()); + this->msgproc->awaitValidation(message.ID()); } BasicSynapse::sendTo(message, dest); @@ -31,40 +31,13 @@ void Networking::Synapse::sendTo(AxonMessage &message, const Socket template void Networking::Synapse::sendPooled(const AxonMessage& message, const Socket &dest) const { - pool->push( { message, dest } ); + this->msgproc->poolMessage( { message, dest } ); } template void Networking::Synapse::onMessageReceived(const AxonMessage& message, const Socket &from) { - if (message.hasFlag(VALIDATE)) - { - sendPooled(AxonMessage(message, 0), from); - } - if (message.hasFlag(ACKNOWLEDGE) && !message.hasFlag(PARTIAL)) - { - auto it = std::find(pendingValidation.begin(), pendingValidation.end(), message.ID()); - if (it != pendingValidation.end()) - pendingValidation.erase(it); - } - if (mmap->contains(message.ID()) || message.hasFlag(PARTIAL)) - { - mmap->append(message); - - if (!message.hasFlag(PARTIAL)) - { - std::shared_ptr res = mmap->collapse(message.ID()); - if (!res) - return; - - SynapseMessageReceivedEvent event_(*res, from); - this->events.invoke(&event_); - } - return; - } - - SynapseMessageReceivedEvent event_ = SynapseMessageReceivedEvent(message, from); - this->events.invoke(&event_); + this->msgproc->process(message, from); } #pragma endregion diff --git a/libraries/networking/synapse/netcontroller/AxonNetworkController.ipp b/libraries/networking/synapse/netcontroller/AxonNetworkController.ipp index 4bb95ec..18c3d5f 100644 --- a/libraries/networking/synapse/netcontroller/AxonNetworkController.ipp +++ b/libraries/networking/synapse/netcontroller/AxonNetworkController.ipp @@ -1,18 +1,17 @@ #pragma once #include -#include namespace Networking { - void AxonNetworkControllerBase::start() { + inline void AxonNetworkControllerBase::start() { this->alive.store(true); } - void AxonNetworkControllerBase::kill() { + inline void AxonNetworkControllerBase::kill() { this->alive.store(false); } - AxonNetworkControllerBase::AxonNetworkControllerBase(SynapseInterface *owner) : + inline AxonNetworkControllerBase::AxonNetworkControllerBase(SynapseInterface *owner) : owningSynapse(owner) {} template @@ -24,7 +23,7 @@ namespace Networking { static_assert(mode == SynapseMode::SERVER); uint8_t ret = initialize_server ( connection, port ); if ( ret != SUCCESS ) { - throw Networking::AxonNetworkingInternalError(ret); + throw AxonNetworkingInternalError(ret); } } @@ -35,9 +34,9 @@ namespace Networking { AxonNetworkControllerBase(owner) { static_assert(mode == SynapseMode::CLIENT); - uint8_t ret = initialize_client ( connection, info.hostname.c_str(), info.port ); + const uint8_t ret = initialize_client ( connection, info.hostname.c_str(), info.port ); if ( ret != SUCCESS ) { - throw Networking::AxonNetworkingInternalError(ret); + throw AxonNetworkingInternalError(ret); } } @@ -67,7 +66,7 @@ namespace Networking { #pragma region SERVER_FUNCTIONS template<> - inline void Networking::BerkeleyAxonNetworkController::listen() + inline void BerkeleyAxonNetworkController::listen() { fd_set master; FD_ZERO(&master); @@ -118,7 +117,7 @@ namespace Networking { } template<> - inline void Networking::BerkeleyAxonNetworkController::listen() + inline void BerkeleyAxonNetworkController::listen() { while (this->isAlive()) { char buffer[SYNAPSE_MESSAGE_SIZE_MAX] = {}; @@ -136,7 +135,7 @@ namespace Networking { #pragma region CLIENT_FUNCTIONS template<> - inline void Networking::BerkeleyAxonNetworkController::listen() { + inline void BerkeleyAxonNetworkController::listen() { SOCKET_T client = connection.socket; while (this->isAlive()) @@ -153,12 +152,12 @@ namespace Networking { } template<> - inline void Networking::BerkeleyAxonNetworkController::listen() { + inline void BerkeleyAxonNetworkController::listen() { SOCKADDR_IN_T host = {}; while (this->isAlive()) { char buffer[SYNAPSE_MESSAGE_SIZE_MAX] = {}; - int32_t size = recv_udp_message(reinterpret_cast (buffer), SYNAPSE_MESSAGE_SIZE_MAX, connection.socket, + const int32_t size = recv_udp_message(buffer, SYNAPSE_MESSAGE_SIZE_MAX, connection.socket, &host); if (size > 0) { owningSynapse->processIncomingMessage(SerializedAxonMessage(buffer, size), connection); diff --git a/libraries/networking/synapse/utils/SynapseEvents.hpp b/libraries/networking/synapse/utils/SynapseEvents.hpp index 256ca87..f9d0b08 100644 --- a/libraries/networking/synapse/utils/SynapseEvents.hpp +++ b/libraries/networking/synapse/utils/SynapseEvents.hpp @@ -19,7 +19,7 @@ namespace Networking { GETTER const AxonMessage& getMessage() const { return message; } GETTER const Socket& getFrom() const { return from; } private: - const AxonMessage& message; + const AxonMessage& message; const Socket& from; }; } diff --git a/libraries/networking/utility/AxonNetworkPointer.hpp b/libraries/networking/utility/AxonNetworkPointer.hpp index 37bb766..d260ffa 100644 --- a/libraries/networking/utility/AxonNetworkPointer.hpp +++ b/libraries/networking/utility/AxonNetworkPointer.hpp @@ -3,41 +3,32 @@ #include #include #include - -#include +#include namespace Networking { template - class AXON_DECLSPEC AxonNetworkPtr { + class AXON_DECLSPEC AxonNetworkPtr : public AxonNetworkObject { static_assert(!std::is_abstract::value); static_assert( - !std::is_trivially_copyable_v(), + std::is_literal_type::value || !std::is_trivially_copyable::value, "Type must be trivially copyable to be compatible with Axon Network Pointer"); public: AxonNetworkPtr() = delete; - + AxonNetworkPtr(SynapseInterface *, T *); virtual ~AxonNetworkPtr() = default; GETTER T *get() const { return ptr; } - void set(T); - T &operator*() const; - T *operator->() const; - protected: virtual void onValueChanged(); - virtual void dispatchValueChangeEvent(); - AxonMessage toMessage() const; - private: T *ptr = nullptr; uint8_t flags = 0; - SynapseInterface *synapse = nullptr; - Socket connected = {}; + bool shouldUpdateSelf = false; EventSystem::AxonEventManager events; }; } diff --git a/libraries/networking/utility/AxonNetworkPointer.ipp b/libraries/networking/utility/AxonNetworkPointer.ipp index e4cfe4f..0310d2f 100644 --- a/libraries/networking/utility/AxonNetworkPointer.ipp +++ b/libraries/networking/utility/AxonNetworkPointer.ipp @@ -1,7 +1,17 @@ #pragma once #include "AxonNetworkPointer.hpp" +#include + +#include "MessageProcessor.hpp" + namespace Networking { + template + AxonNetworkPtr::AxonNetworkPtr(SynapseInterface * synapse, T * ptrTo) : + AxonNetworkObject(synapse), + ptr(ptrTo) + {} + template void AxonNetworkPtr::set(T val) { *ptr = val; @@ -26,7 +36,12 @@ namespace Networking { template void AxonNetworkPtr::dispatchValueChangeEvent() { - synapse->sendTo(this->toMessage(), connected); + if (!ready()) { + shouldUpdateSelf = true; + return; + } + AxonMessage _tmp = this->toMessage(); + synapse->send(_tmp); } template diff --git a/libraries/networking/utility/MessageProcessor.cpp b/libraries/networking/utility/MessageProcessor.cpp new file mode 100644 index 0000000..6a6512a --- /dev/null +++ b/libraries/networking/utility/MessageProcessor.cpp @@ -0,0 +1,55 @@ +#include "MessageProcessor.hpp" +#include + +#include + +namespace Networking { + MessageProcessor::MessageProcessor(SynapseInterface *owner) : owner(owner) { + } + + void MessageProcessor::process(const AxonMessage &message, const Socket &from) { + if (message.hasFlag(VALIDATE)) + { + AxonMessage reply(message, 0); + owner->sendTo(reply, from); + } + if (message.hasFlag(NETOBJ_INI)) { + RequestUniqueIDProto proto = * static_cast( message.getMessage() ); + + assert (!message.hasFlag(VALIDATE)); + assert (message.getSize() == sizeof(RequestUniqueIDProto)); + + proto.serverSideID = getObjectID(); + + AxonMessage reply(&proto, sizeof(proto), 0, NETOBJ_REPL); + + owner->sendTo(reply, from); + } + if (message.hasFlag(ACKNOWLEDGE) && !message.hasFlag(PARTIAL)) + { + if (const auto it = std::find( + pendingValidation.begin(), + pendingValidation.end(), message.ID()); it != pendingValidation.end()) + pendingValidation.erase(it); + } + if (mmap->contains(message.ID()) || message.hasFlag(PARTIAL)) + { + mmap->append(message); + + if (!message.hasFlag(PARTIAL)) + { + const std::shared_ptr res = mmap->collapse(message.ID()); + if (!res) + return; + + SynapseMessageReceivedEvent event_(*res, from); + this->owner->getEventManager().invoke(&event_); + } + + return; + } + + SynapseMessageReceivedEvent event_(message, from); + this->owner->getEventManager().invoke(&event_); + } +} // Networking \ No newline at end of file diff --git a/libraries/networking/utility/MessageProcessor.hpp b/libraries/networking/utility/MessageProcessor.hpp new file mode 100644 index 0000000..dfcfbb5 --- /dev/null +++ b/libraries/networking/utility/MessageProcessor.hpp @@ -0,0 +1,49 @@ +#pragma once + +#include +#include +#include + +namespace Networking { + +#define ADD_MODULE(TYPENAME, NAME, ...) \ + std::unique_ptr NAME = std::make_unique(__VA_ARGS__) + +class AXON_DECLSPEC MessageProcessor { +public: + struct RequestUniqueIDProto { + uint32_t clientSideID = 0; + uint64_t serverSideID = 0; + + static uint32_t generateID() { + static uint32_t uniqueID = 0; + return ++uniqueID; + } + }; + + MessageProcessor() = delete; + + explicit MessageProcessor(SynapseInterface *); + + MessageProcessor & operator= (const MessageProcessor &) = delete; + MessageProcessor & operator= (MessageProcessor&&) = delete; + + void process(const AxonMessage &, const Socket &); + void awaitValidation(uint64_t id) { pendingValidation.push_back(id); } + + GETTER MessagePoolNodePtr processPool() const { return pool->pop(); } + void poolMessage(const MessagePoolNode &node) const { pool->push(node); } +protected: + GETTER static uint64_t getObjectID() { + static uint64_t lastID = 0; + return ++lastID; + } +private: + SynapseInterface *owner; + + std::vector pendingValidation; + ADD_MODULE(MessageMapBase, mmap); + ADD_MODULE(MessagePoolBase, pool); +}; + +} // Networking diff --git a/tests/basic_checks/CMakeLists.txt b/tests/basic_checks/CMakeLists.txt deleted file mode 100644 index abf4287..0000000 --- a/tests/basic_checks/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -project ("AxonEngine.tests.basic_checks") -include ("CTest") - -# TEST FILES -enable_testing() - -list_all_tests("test_*.cxx" networking) - -include_directories("../../libraries") diff --git a/tests/basic_checks/test_event_system.cxx b/tests/basic_checks/test_event_system.cxx deleted file mode 100644 index b7ce10f..0000000 --- a/tests/basic_checks/test_event_system.cxx +++ /dev/null @@ -1,52 +0,0 @@ -#include - -#include -#include - - -class TestEvent : public EventSystem::AxonEvent -{ -private: - uint8_t data; - bool isChecked = false; -public: - TestEvent() = delete; - - explicit TestEvent(uint8_t data = 0) - { - this->data = data; - } - - inline uint8_t get_data() const { return data; } -}; - - -void callback(const TestEvent& event) -{ - uint8_t data = event.get_data(); - assert(data == 3); -} - -void callback2(const TestEvent& event) -{ - uint8_t data = event.get_data(); - assert(data == 3); -} - -int main() -{ - /* Local events */ - TestEvent event(3); - - EventSystem::AxonEventManager manager; - - manager.subscribe(callback); - manager.invoke(&event); - - /* Global event manager */ - EventSystem::GlobalEventManager& g_manager = EventSystem::GlobalEventManager::Instance(); - g_manager.subscribe(callback); - g_manager.subscribe(callback2); - - g_manager.invoke(&event); -} diff --git a/tests/gtest/FakeNetworkController/FakeNetworkController.hpp b/tests/gtest/FakeNetworkController/FakeNetworkController.hpp index a468aff..080963b 100644 --- a/tests/gtest/FakeNetworkController/FakeNetworkController.hpp +++ b/tests/gtest/FakeNetworkController/FakeNetworkController.hpp @@ -31,7 +31,7 @@ namespace TestUtils { static uint32_t desc = 0; return ++desc; } - private: + std::map pool = {}; std::map> nodes = {}; }; @@ -48,7 +48,7 @@ namespace TestUtils { void sendTo(Networking::AxonMessage&, const Networking::NetworkNodeInfo&) override; - GETTER Networking::SynapseInterface * owner() { return owningSynapse; } + GETTER Networking::SynapseInterface * owner() const { return owningSynapse; } protected: void sendSerializedTo(const Networking::SerializedAxonMessage&, const Networking::NetworkNodeInfo&) override; diff --git a/tests/gtest/FakeNetworkController/FakeNetworkController.ipp b/tests/gtest/FakeNetworkController/FakeNetworkController.ipp index fd612cd..e13649a 100644 --- a/tests/gtest/FakeNetworkController/FakeNetworkController.ipp +++ b/tests/gtest/FakeNetworkController/FakeNetworkController.ipp @@ -1,7 +1,7 @@ #pragma once inline void TestUtils::FakeNetwork::sendto(const Networking::SerializedAxonMessage &serialized, uint32_t socket, uint32_t from) { - pool[socket]->owner()->processIncomingMessage(serialized, { static_cast( socket ), {} }); + pool[socket]->owner()->processIncomingMessage(serialized, { static_cast( from ), {} }); } inline uint32_t TestUtils::FakeNetwork::create( @@ -17,7 +17,7 @@ inline uint32_t TestUtils::FakeNetwork::connect(const std::string &hostname, uin return this->nodes[hostname][port]; } -void TestUtils::FakeNetwork::bind(uint32_t desc, TestUtils::FakeNetworkController *controller) { +inline void TestUtils::FakeNetwork::bind(uint32_t desc, FakeNetworkController *controller) { pool[desc] = controller; } diff --git a/tests/gtest/entry.cpp b/tests/gtest/entry.cpp new file mode 100644 index 0000000..217bcfc --- /dev/null +++ b/tests/gtest/entry.cpp @@ -0,0 +1,8 @@ +#include + + +int main(int argc, char* argv[]) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/tests/gtest/test_data_buffer.cpp b/tests/gtest/test_data_buffer.cpp index b7ccb99..b902dc3 100644 --- a/tests/gtest/test_data_buffer.cpp +++ b/tests/gtest/test_data_buffer.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include TEST(TEST_BINARY_STREAM, TEST_COMMON) @@ -20,9 +20,3 @@ TEST(TEST_BINARY_STREAM, TEST_COMMON) ASSERT_NE(newStream.size(), 0); ASSERT_NE(newStream.data(), nullptr); } - -int main(int argc, char* argv[]) -{ - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} \ No newline at end of file diff --git a/tests/gtest/test_event_system.cpp b/tests/gtest/test_event_system.cpp new file mode 100644 index 0000000..1b0fea4 --- /dev/null +++ b/tests/gtest/test_event_system.cpp @@ -0,0 +1,77 @@ +#include + +#include + +class TestEvent : public EventSystem::AxonEvent +{ +public: + TestEvent() = delete; + + explicit TestEvent(uint8_t data = 0) + { + this->data = data; + } + + uint8_t get_data() const { return data; } +private: + uint8_t data; + bool isChecked = false; +}; + + +void callback(const TestEvent& event) +{ + uint8_t data = event.get_data(); + assert(data == 3); +} + +void callback2(const TestEvent& event) +{ + uint8_t data = event.get_data(); + assert(data == 3); +} + +TEST(TEST_EVENT_SYSTEM, TEST_EVENT_SYSTEM_GENERAL) +{ + /* Local events */ + TestEvent event(3); + + EventSystem::AxonEventManager manager; + + manager.subscribe(callback); + manager.invoke(&event); + + /* Global event manager */ + EventSystem::GlobalEventManager& g_manager = EventSystem::GlobalEventManager::Instance(); + g_manager.subscribe(callback); + g_manager.subscribe(callback2); + + g_manager.invoke(&event); +} + +TEST(TEST_EVENT_SYSTEM, TEST_EVENT_SYSTEM_W_CLASS_OBJ) +{ + /* Local events */ + TestEvent event(3); + EventSystem::GlobalEventManager& g_manager = EventSystem::GlobalEventManager::Instance(); + + class TestEventCheckClass { + public: + TestEventCheckClass() { + EventSystem::GlobalEventManager::Instance().subscribe< + TestEventCheckClass, TestEvent + >(&TestEventCheckClass::callback, this); + } + + void callback(const TestEvent &) { + call = true; + } + + bool check() const { return call; } + private: + bool call = false; + } instance; + + g_manager.invoke(&event); + ASSERT_TRUE(instance.check()); +} diff --git a/tests/gtest/test_message_pool.cpp b/tests/gtest/test_message_pool.cpp index d5e0799..2ec4b16 100644 --- a/tests/gtest/test_message_pool.cpp +++ b/tests/gtest/test_message_pool.cpp @@ -1,5 +1,5 @@ #include -#include +#include TEST(TEST_MESSAGE_POOL, TEST_REGULAR) @@ -23,10 +23,3 @@ TEST(TEST_MESSAGE_POOL, TEST_REGULAR) ASSERT_FALSE(pool.getPoolSize()); ASSERT_NE(pNode1.get(), pNode2.get()); } - - -int main(int argc, char* argv[]) -{ - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} \ No newline at end of file diff --git a/tests/gtest/test_network_pointer.cpp b/tests/gtest/test_network_pointer.cpp new file mode 100644 index 0000000..dfa3463 --- /dev/null +++ b/tests/gtest/test_network_pointer.cpp @@ -0,0 +1,16 @@ +#include +#include +#include "FakeNetworkController/FakeNetworkController.hpp" +#include "utility/AxonNetworkPointer.hpp" + +TEST(TEST_NETWORK_POINTER, TEST_GET_SERVER_ID) { + Networking::Synapse server(10432); + Networking::Synapse client({"test-nodes-fake-host", 10432}); + + server.start(); + client.start(); + uint8_t data = 0; + Networking::AxonNetworkPtr ptr(&client, &data); + + ASSERT_TRUE(ptr.ready()); +} diff --git a/tests/gtest/test_networking.cpp b/tests/gtest/test_networking.cpp index 399bd8d..04dd0e4 100644 --- a/tests/gtest/test_networking.cpp +++ b/tests/gtest/test_networking.cpp @@ -4,9 +4,3 @@ TEST(TESTS_BACKEND, TEST_BACKEND_GENERAL) { } - -int main(int argc, char* argv[]) -{ - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/tests/gtest/test_serialization.cpp b/tests/gtest/test_serialization.cpp index d533329..9667962 100644 --- a/tests/gtest/test_serialization.cpp +++ b/tests/gtest/test_serialization.cpp @@ -122,9 +122,3 @@ TEST(TEST_SERIALIZATION, TEST_MESSAGE_SPLIT) { message_.~AxonMessage(); ASSERT_STREQ(static_cast(ptr->getMessage()), " World!"); } - -int main(int argc, char* argv[]) -{ - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/tests/gtest/test_synapse.cpp b/tests/gtest/test_synapse.cpp index 6ccc5f5..6720219 100644 --- a/tests/gtest/test_synapse.cpp +++ b/tests/gtest/test_synapse.cpp @@ -1,13 +1,25 @@ #include -#include +#include #include "FakeNetworkController/FakeNetworkController.hpp" #include bool hasVisited = false; -void onMessageReceived(const Networking::SynapseMessageReceivedEvent& event) { - ASSERT_STREQ(static_cast(event.getMessage().getMessage()), "Hello World!"); - hasVisited = true; +namespace { + void onMessageReceived(const Networking::SynapseMessageReceivedEvent& event) { + ASSERT_STREQ(static_cast(event.getMessage().getMessage()), "Hello World!"); + hasVisited = true; + } + + void onMessageReceivedWithUniqueID(const Networking::SynapseMessageReceivedEvent& event) { + static uint64_t lastTaken = 0; + + if (!event.getMessage().hasFlag(Networking::NETOBJ_REPL)) return; + Networking::MessageProcessor::RequestUniqueIDProto repl = * static_cast< Networking::MessageProcessor::RequestUniqueIDProto * > ( event.getMessage().getMessage() ); + ASSERT_NE( repl.serverSideID, lastTaken ); + lastTaken = repl.serverSideID; + hasVisited = true; + } } TEST(TEST_SYNAPSE, TEST_FAKE_NETWORK) { @@ -28,8 +40,21 @@ TEST(TEST_SYNAPSE, TEST_FAKE_NETWORK) { hasVisited = false; } -int main(int argc, char* argv[]) -{ - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); +TEST(TEST_SYNAPSE, TEST_GET_SERVER_ID) { + Networking::Synapse server(10432); + Networking::Synapse client({"test-nodes-fake-host", 10432}); + client.getEventManager().subscribe(onMessageReceivedWithUniqueID); + + server.start(); + client.start(); + + Networking::MessageProcessor::RequestUniqueIDProto repl = { 0, 0 }; + Networking::AxonMessage message( &repl, sizeof(repl), 0, Networking::NETOBJ_INI ); + + client.send(message); + client.send(message); + client.send(message); + + ASSERT_TRUE(hasVisited); } + diff --git a/tests/performance/CMakeLists.txt b/tests/performance/CMakeLists.txt index a03e6f5..b66e6aa 100644 --- a/tests/performance/CMakeLists.txt +++ b/tests/performance/CMakeLists.txt @@ -1,7 +1,7 @@ project ("AxonEngine.tests.performance") set (LIST_LIBRARIES networking testutils) -list_all_tests("perf_*.cpp" ${LIST_LIBRARIES}) +list_all_tests_separate("perf_*.cpp" ${LIST_LIBRARIES}) include_directories("../../libraries") include_directories("../utils/testutils") diff --git a/tests/performance/perf_synapse.cpp b/tests/performance/perf_synapse.cpp index 1d0396c..d243b48 100644 --- a/tests/performance/perf_synapse.cpp +++ b/tests/performance/perf_synapse.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include #include From a3e5b8942e65b168769aca9905ceb8aaa4f422f3 Mon Sep 17 00:00:00 2001 From: Keyboard Destroyer <43577127+kbrddestroyer@users.noreply.github.com> Date: Mon, 9 Jun 2025 11:14:21 +0300 Subject: [PATCH 33/47] Added unsubscribe method, which utilises some hacks, but still works and passes tests (#129) --- libraries/events/AxonEvent.cpp | 10 +-- libraries/events/AxonEvent.hpp | 30 +++++++- libraries/events/AxonEvent.ipp | 37 +++++++++- .../networking/utility/AxonNetworkPointer.hpp | 4 +- .../networking/utility/AxonNetworkPointer.ipp | 3 - tests/gtest/test_event_system.cpp | 69 +++++++++++++++++++ 6 files changed, 137 insertions(+), 16 deletions(-) diff --git a/libraries/events/AxonEvent.cpp b/libraries/events/AxonEvent.cpp index 6a22b79..5abb61a 100644 --- a/libraries/events/AxonEvent.cpp +++ b/libraries/events/AxonEvent.cpp @@ -3,7 +3,7 @@ EventSystem::AxonEventManager::~AxonEventManager() { - for (std::pair>> calls : subscribers) + for (auto & calls : subscribers) { calls.second.clear(); } @@ -12,12 +12,12 @@ EventSystem::AxonEventManager::~AxonEventManager() void EventSystem::AxonEventManager::invoke(AxonEvent* event) { - std::type_index type = std::type_index(typeid(*event)); - std::vector> calls = subscribers[type]; + const auto type = std::type_index(typeid(*event)); + calls_c calls = subscribers[type]; - for (const std::function& callback : calls) + for (const auto & callback : calls) { - callback(event); + callback.second(event); } } diff --git a/libraries/events/AxonEvent.hpp b/libraries/events/AxonEvent.hpp index 16eae5f..d5e20e3 100644 --- a/libraries/events/AxonEvent.hpp +++ b/libraries/events/AxonEvent.hpp @@ -4,6 +4,7 @@ #include #include +#include namespace EventSystem { @@ -19,27 +20,50 @@ namespace EventSystem /** * EventManager class is capable of dispatching triggered events.\n * Usage: + *
* EventManager could be created literally anywhere. * Callback method can be attached with subscribe() method. It will be dispatched when * invoke() message is called. + *
+ *
+ * IMPORTANT NOTE: + *
+ * Please, make sure that you unsubscribe class method in destructor. EventManager contains class method reference and will try to call it, even if object is nonexistent. This is undefined behaviour and most likely will cause a segmentation fault on Unix systems and SEH exception on Windows. * * @note see GlobalEventManager * @note see client-server example */ class AxonEventManager { + protected: + typedef uint64_t desc_t; + typedef std::type_index primary_key_t; + typedef std::function event_call_t; + typedef std::unordered_map calls_c; public: AxonEventManager() = default; virtual ~AxonEventManager(); template - void subscribe(std::function); + void subscribe(std::function); template void subscribe(void (C::* callback)(const T&), C *instance); - + + template + void unsubscribe(std::function); + + template + void unsubscribe(void (C::* callback)(const T&), C *instance); + void invoke(AxonEvent *); + protected: + template + desc_t generateDescriptor(std::function); + + template + desc_t generateDescriptor(void (C::* callback)(const T&), C *instance); private: - std::unordered_map>> subscribers; + std::unordered_map subscribers; }; /** diff --git a/libraries/events/AxonEvent.ipp b/libraries/events/AxonEvent.ipp index 93e7625..ce219e9 100644 --- a/libraries/events/AxonEvent.ipp +++ b/libraries/events/AxonEvent.ipp @@ -3,9 +3,11 @@ template void EventSystem::AxonEventManager::subscribe(std::function callback) { - std::type_index type = std::type_index(typeid(T)); + const auto type = std::type_index(typeid(T)); + + desc_t desc = generateDescriptor(callback); - subscribers[type].push_back( + subscribers[type][desc] = ( [callback](AxonEvent* base_event) { if (T* event = dynamic_cast(base_event)) { @@ -19,7 +21,9 @@ template void EventSystem::AxonEventManager::subscribe(void(C::* callback)(const T&), C* instance) { const auto type = std::type_index(typeid(T)); - subscribers[type].push_back( + desc_t desc = generateDescriptor(callback, instance); + + subscribers[type][desc] = ( [callback, instance](AxonEvent* base_event) { if (T* event = dynamic_cast(base_event)) { @@ -28,3 +32,30 @@ void EventSystem::AxonEventManager::subscribe(void(C::* callback)(const T&), C* } ); } + +template +void EventSystem::AxonEventManager::unsubscribe(std::function callback) { + const auto type = std::type_index(typeid(T)); + desc_t desc = generateDescriptor(callback); + + subscribers[type].erase(desc); +} + +template +void EventSystem::AxonEventManager::unsubscribe(void (C::* callback)(const T&), C *instance) { + const auto type = std::type_index(typeid(T)); + desc_t desc = generateDescriptor(callback, instance); + + subscribers[type].erase(desc); +} + +template +uint64_t EventSystem::AxonEventManager::generateDescriptor(std::function callback) { + const auto fPtr = callback.template target(); + return std::hash() (*(void**) &fPtr); +} + +template +uint64_t EventSystem::AxonEventManager::generateDescriptor(void (C::* callback)(const T&), C *instance) { + return std::hash() (instance); +} diff --git a/libraries/networking/utility/AxonNetworkPointer.hpp b/libraries/networking/utility/AxonNetworkPointer.hpp index d260ffa..b80c541 100644 --- a/libraries/networking/utility/AxonNetworkPointer.hpp +++ b/libraries/networking/utility/AxonNetworkPointer.hpp @@ -10,12 +10,12 @@ namespace Networking { class AXON_DECLSPEC AxonNetworkPtr : public AxonNetworkObject { static_assert(!std::is_abstract::value); static_assert( - std::is_literal_type::value || !std::is_trivially_copyable::value, + std::is_literal_type_v || !std::is_trivially_copyable::value, "Type must be trivially copyable to be compatible with Axon Network Pointer"); public: AxonNetworkPtr() = delete; AxonNetworkPtr(SynapseInterface *, T *); - virtual ~AxonNetworkPtr() = default; + ~AxonNetworkPtr() override = default; GETTER T *get() const { return ptr; } void set(T); diff --git a/libraries/networking/utility/AxonNetworkPointer.ipp b/libraries/networking/utility/AxonNetworkPointer.ipp index 0310d2f..6de6329 100644 --- a/libraries/networking/utility/AxonNetworkPointer.ipp +++ b/libraries/networking/utility/AxonNetworkPointer.ipp @@ -1,8 +1,5 @@ #pragma once -#include "AxonNetworkPointer.hpp" - #include - #include "MessageProcessor.hpp" namespace Networking { diff --git a/tests/gtest/test_event_system.cpp b/tests/gtest/test_event_system.cpp index 1b0fea4..b4e993f 100644 --- a/tests/gtest/test_event_system.cpp +++ b/tests/gtest/test_event_system.cpp @@ -62,6 +62,11 @@ TEST(TEST_EVENT_SYSTEM, TEST_EVENT_SYSTEM_W_CLASS_OBJ) TestEventCheckClass, TestEvent >(&TestEventCheckClass::callback, this); } + ~TestEventCheckClass() { + EventSystem::GlobalEventManager::Instance().unsubscribe< + TestEventCheckClass, TestEvent + >(&TestEventCheckClass::callback, this); + } void callback(const TestEvent &) { call = true; @@ -75,3 +80,67 @@ TEST(TEST_EVENT_SYSTEM, TEST_EVENT_SYSTEM_W_CLASS_OBJ) g_manager.invoke(&event); ASSERT_TRUE(instance.check()); } + +TEST(TEST_EVENT_SYSTEM, TEST_UNSUBSCRIBE_CLASS_MEMBER) +{ + /* Local events */ + TestEvent event(3); + EventSystem::GlobalEventManager& g_manager = EventSystem::GlobalEventManager::Instance(); + + class TestEventCheckClass { + public: + TestEventCheckClass() { + EventSystem::GlobalEventManager::Instance().subscribe< + TestEventCheckClass, TestEvent + >(&TestEventCheckClass::callback, this); + } + + ~TestEventCheckClass() { + EventSystem::GlobalEventManager::Instance().unsubscribe< + TestEventCheckClass, TestEvent + >(&TestEventCheckClass::callback, this); + } + + void callback(const TestEvent &) { + call = true; + } + + bool check() const { return call; } + + void reset() { call = false; } + private: + bool call = false; + } instance1, instance2; + + g_manager.invoke(&event); + ASSERT_TRUE(instance1.check()); + ASSERT_TRUE(instance2.check()); + instance1.reset(); + instance2.reset(); + ASSERT_FALSE(instance1.check()); + ASSERT_FALSE(instance2.check()); + g_manager.unsubscribe< + TestEventCheckClass, TestEvent + >(&TestEventCheckClass::callback, &instance1); + g_manager.invoke(&event); + ASSERT_FALSE(instance1.check()); + ASSERT_TRUE(instance2.check()); + g_manager.unsubscribe< + TestEventCheckClass, TestEvent + >(&TestEventCheckClass::callback, &instance2); +} + +void callback3(const TestEvent& event) +{ + throw 1; +} + +TEST(TEST_EVENT_SYSTEM, TEST_UNSUBSCRIBE_FUNCTION) { + TestEvent event(3); + EventSystem::AxonEventManager g_manager; + + g_manager.subscribe(callback3); + g_manager.unsubscribe(callback3); + + g_manager.invoke(&event); +} From b6d4497efb5ecd070613ea5e1dd62f8fd577ef1a Mon Sep 17 00:00:00 2001 From: KbrdDestroyer Date: Mon, 9 Jun 2025 14:14:24 +0300 Subject: [PATCH 34/47] Added unsubscribe method to AxonNetworkObject destructor --- libraries/messages/AxonMessage.hpp | 4 ++-- libraries/networking/AxonNetworkObject.cpp | 13 ++++++++++--- libraries/networking/AxonNetworkObject.hpp | 4 ++-- libraries/networking/utility/AxonNetworkPointer.hpp | 2 +- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/libraries/messages/AxonMessage.hpp b/libraries/messages/AxonMessage.hpp index 824566a..398c968 100644 --- a/libraries/messages/AxonMessage.hpp +++ b/libraries/messages/AxonMessage.hpp @@ -52,8 +52,8 @@ namespace Networking ~SerializedAxonMessage(); - GETTER size_t getSize() const { return size; } - GETTER const char* getBits() const { return bytes; } + WGETTER( size_t getSize() ) { return size; } + WGETTER ( const char* getBits() ) { return bytes; } SerializedAxonMessage& operator=(const SerializedAxonMessage&); SerializedAxonMessage& operator=(SerializedAxonMessage&&) noexcept; diff --git a/libraries/networking/AxonNetworkObject.cpp b/libraries/networking/AxonNetworkObject.cpp index feb8c09..e7fe7d1 100644 --- a/libraries/networking/AxonNetworkObject.cpp +++ b/libraries/networking/AxonNetworkObject.cpp @@ -1,12 +1,9 @@ #include "AxonNetworkObject.hpp" #include - - Networking::AxonNetworkObject::AxonNetworkObject(SynapseInterface * synapse) : synapse(synapse) { if (synapse) { - synapse->getEventManager().subscribe< AxonNetworkObject, SynapseMessageReceivedEvent >(&AxonNetworkObject::onIDResolved, this); @@ -14,6 +11,12 @@ Networking::AxonNetworkObject::AxonNetworkObject(SynapseInterface * synapse) : } } +Networking::AxonNetworkObject::~AxonNetworkObject() { + synapse->getEventManager().unsubscribe< + AxonNetworkObject, SynapseMessageReceivedEvent + >(&AxonNetworkObject::onIDResolved, this); +} + void Networking::AxonNetworkObject::resolveNetworkID() { this->clientID = MessageProcessor::RequestUniqueIDProto::generateID(); @@ -34,6 +37,10 @@ void Networking::AxonNetworkObject::onIDResolved(const SynapseMessageReceivedEve if (repl.clientSideID != this->clientID) return; this->serverID = repl.serverSideID; + + synapse->getEventManager().unsubscribe< + AxonNetworkObject, SynapseMessageReceivedEvent + >(&AxonNetworkObject::onIDResolved, this); } diff --git a/libraries/networking/AxonNetworkObject.hpp b/libraries/networking/AxonNetworkObject.hpp index b75fef0..a71cc31 100644 --- a/libraries/networking/AxonNetworkObject.hpp +++ b/libraries/networking/AxonNetworkObject.hpp @@ -8,9 +8,9 @@ namespace Networking { public: AxonNetworkObject() = delete; AxonNetworkObject( SynapseInterface * ); - virtual ~AxonNetworkObject() = default; + virtual ~AxonNetworkObject(); - WGETTER ( bool ready() ) { return serverID != 0; } + WGETTER( bool ready() ) { return serverID != 0; } WGETTER( uint64_t id() ) { return serverID; } protected: void resolveNetworkID(); diff --git a/libraries/networking/utility/AxonNetworkPointer.hpp b/libraries/networking/utility/AxonNetworkPointer.hpp index b80c541..9662d0f 100644 --- a/libraries/networking/utility/AxonNetworkPointer.hpp +++ b/libraries/networking/utility/AxonNetworkPointer.hpp @@ -10,7 +10,7 @@ namespace Networking { class AXON_DECLSPEC AxonNetworkPtr : public AxonNetworkObject { static_assert(!std::is_abstract::value); static_assert( - std::is_literal_type_v || !std::is_trivially_copyable::value, + std::is_trivially_copyable::value, "Type must be trivially copyable to be compatible with Axon Network Pointer"); public: AxonNetworkPtr() = delete; From 52ab55bdfd3afcf6a342b9e199bb7b06eb9868ee Mon Sep 17 00:00:00 2001 From: KbrdDestroyer Date: Mon, 9 Jun 2025 14:24:10 +0300 Subject: [PATCH 35/47] Migrated SerializedAxonMessage to the rule of 0 --- libraries/messages/AxonMessage.cpp | 64 +++---------------- libraries/messages/AxonMessage.hpp | 14 +--- .../synapse/utils/SynapseUtility.hpp | 4 +- 3 files changed, 14 insertions(+), 68 deletions(-) diff --git a/libraries/messages/AxonMessage.cpp b/libraries/messages/AxonMessage.cpp index 02c6f71..a0d8d18 100644 --- a/libraries/messages/AxonMessage.cpp +++ b/libraries/messages/AxonMessage.cpp @@ -8,70 +8,24 @@ Networking::SerializedAxonMessage::SerializedAxonMessage(const AxonMessage &mess size(message.getSize()) { const TAG_T tag = compressTag(message.getPartID(), message.getFlags(), message.ID()); - bytes = serialize(static_cast(message.getMessage()), message.getSize(), tag, &size); + const char *buffer = serialize(static_cast(message.getMessage()), message.getSize(), tag, &size); + + bytes = std::shared_ptr( buffer ); } Networking::SerializedAxonMessage::SerializedAxonMessage(const char* bits, size64_t actualSize) : size(actualSize) { if (actualSize > 0) { - bytes = new char[size]; - memcpy(const_cast(bytes), bits, size); - } -} - -Networking::SerializedAxonMessage::SerializedAxonMessage(const SerializedAxonMessage &message) : - size(message.size), - offset(message.offset) -{ - if (size > 0) - { - bytes = new char[size]; - memcpy(const_cast(bytes), message.bytes, size); + bytes = std::make_shared(size); + memcpy(const_cast(bytes.get()), bits, size); } } -Networking::SerializedAxonMessage::SerializedAxonMessage(SerializedAxonMessage &&message) noexcept : - size(std::exchange(message.size, 0)), - bytes(std::exchange(message.bytes, nullptr)) -{} - -Networking::SerializedAxonMessage::~SerializedAxonMessage() { - if (bytes && owning) - delete[] bytes; -} - TAG_T Networking::SerializedAxonMessage::compressTag(uint8_t optionalData, uint8_t newFlags, uint16_t id) { return ((optionalData << 8) | newFlags) << 16 | id; } -Networking::SerializedAxonMessage & -Networking::SerializedAxonMessage::operator=(const SerializedAxonMessage &message) { - if (&message == this) - return *this; - - size = message.size; - - if (size > 0) - { - bytes = new char[size]; - memcpy(const_cast(bytes), message.bytes, size); - } - - return * this; -} - -Networking::SerializedAxonMessage & -Networking::SerializedAxonMessage::operator=(SerializedAxonMessage &&message) noexcept { - if (&message == this) - return *this; - - std::exchange(size, message.size); - std::exchange(bytes, message.bytes); - - return * this; -} - #pragma endregion #pragma region AxonMessage @@ -91,14 +45,16 @@ Networking::AxonMessage::AxonMessage(const void* message, size64_t size, uint8_t Networking::AxonMessage::AxonMessage(const SerializedAxonMessage &serialized) { TAG_T tag; - deserialize( - serialized.bytes, + uint8_t _ret = deserialize( + serialized.bytes.get(), serialized.size, &this->message, &this->size, &tag ); - decompressTag(tag, &partID, &flags, &this->uniqueID); + + if (_ret == 0) + decompressTag(tag, &partID, &flags, &this->uniqueID); } Networking::AxonMessage::AxonMessage(const AxonMessage &message, const uint8_t additionalFlags) : diff --git a/libraries/messages/AxonMessage.hpp b/libraries/messages/AxonMessage.hpp index 398c968..df6abc7 100644 --- a/libraries/messages/AxonMessage.hpp +++ b/libraries/messages/AxonMessage.hpp @@ -46,25 +46,17 @@ namespace Networking public: SerializedAxonMessage() = delete; SerializedAxonMessage(const char*, size64_t); - SerializedAxonMessage(const SerializedAxonMessage&); explicit SerializedAxonMessage(const AxonMessage&); - SerializedAxonMessage(SerializedAxonMessage&&) noexcept; - - ~SerializedAxonMessage(); WGETTER( size_t getSize() ) { return size; } - WGETTER ( const char* getBits() ) { return bytes; } - - SerializedAxonMessage& operator=(const SerializedAxonMessage&); - SerializedAxonMessage& operator=(SerializedAxonMessage&&) noexcept; + WGETTER ( const char* getBits() ) { return bytes.get(); } protected: static TAG_T compressTag(uint8_t, uint8_t, uint16_t); private: size64_t size = 0; - uint16_t uniqueID = 0; uintptr_t offset = 0; - bool owning = true; // todo: `uint16_t _refcnt;` or shared_ptr around bytes array - const char* bytes = nullptr; + + std::shared_ptr bytes = nullptr; friend class AxonMessage; }; diff --git a/libraries/networking/synapse/utils/SynapseUtility.hpp b/libraries/networking/synapse/utils/SynapseUtility.hpp index 715bff7..beca5d1 100644 --- a/libraries/networking/synapse/utils/SynapseUtility.hpp +++ b/libraries/networking/synapse/utils/SynapseUtility.hpp @@ -23,9 +23,7 @@ namespace Networking { }; /** - * Low-level connection info for convenient storage - * TODO: - * - Research replacement + * Low-level connection info for convenient storage. */ struct ConnectionInfo { From 2cfc59d6d6b3f41a329f5fa7fcebaa7ce763be59 Mon Sep 17 00:00:00 2001 From: KbrdDestroyer Date: Mon, 9 Jun 2025 14:37:20 +0300 Subject: [PATCH 36/47] Removed deprecated construction from ConnectionInfo struct - using hostname - port pair instead --- examples/basics/basic-synapse/client.cpp | 4 +--- libraries/networking/synapse/Synapse.hpp | 6 +++--- tests/performance/perf_synapse.cpp | 2 +- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/examples/basics/basic-synapse/client.cpp b/examples/basics/basic-synapse/client.cpp index e51effe..f7d5ff3 100644 --- a/examples/basics/basic-synapse/client.cpp +++ b/examples/basics/basic-synapse/client.cpp @@ -34,11 +34,9 @@ void onMessageReceived(const Networking::SynapseMessageReceivedEvent& event) int main() { - Networking::ConnectionInfo connection = { "localhost", 10423 }; - Networking::AsyncSynapse< Networking::BerkeleyAxonNetworkController - > clientConnection(connection); + > clientConnection("localhost", 10423); clientConnection.getEventManager().subscribe(onMessageReceived); clientConnection.start(); diff --git a/libraries/networking/synapse/Synapse.hpp b/libraries/networking/synapse/Synapse.hpp index 068a8d4..a526ae3 100644 --- a/libraries/networking/synapse/Synapse.hpp +++ b/libraries/networking/synapse/Synapse.hpp @@ -23,7 +23,7 @@ namespace Networking /** Initializes Synapse in server mode */ explicit Synapse(uint32_t port) : BasicSynapse(port) {} /** Initialize Synapse in client mode */ - explicit Synapse(const ConnectionInfo &info) : BasicSynapse(info) {} + Synapse (const char *hostname, const uint32_t port) : BasicSynapse({hostname, port}) {} ~Synapse() override = default; #pragma endregion @@ -55,9 +55,9 @@ namespace Networking explicit AsyncSynapse(uint32_t port) : Synapse(port) {} /** Initialize Synapse in client mode */ - explicit AsyncSynapse(const ConnectionInfo &info) : Synapse(info) {} + explicit AsyncSynapse (const char *hostname, const uint32_t port) : Synapse(hostname, port) {} - ~AsyncSynapse() override; + ~AsyncSynapse() override; void start() override; void kill() override; diff --git a/tests/performance/perf_synapse.cpp b/tests/performance/perf_synapse.cpp index d243b48..16af340 100644 --- a/tests/performance/perf_synapse.cpp +++ b/tests/performance/perf_synapse.cpp @@ -9,7 +9,7 @@ int main() { > server(10432); Networking::AsyncSynapse< Networking::BerkeleyAxonNetworkController - > client({"localhost", 10432}); + > client("localhost", 10432); server.start(); client.start(); From 3e87a1ec71d81a83eaf68aa0735f694a82df91c8 Mon Sep 17 00:00:00 2001 From: KbrdDestroyer Date: Mon, 9 Jun 2025 15:45:34 +0300 Subject: [PATCH 37/47] Removed deprecated construction --- tests/gtest/test_network_pointer.cpp | 2 +- tests/gtest/test_synapse.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/gtest/test_network_pointer.cpp b/tests/gtest/test_network_pointer.cpp index dfa3463..62cf471 100644 --- a/tests/gtest/test_network_pointer.cpp +++ b/tests/gtest/test_network_pointer.cpp @@ -5,7 +5,7 @@ TEST(TEST_NETWORK_POINTER, TEST_GET_SERVER_ID) { Networking::Synapse server(10432); - Networking::Synapse client({"test-nodes-fake-host", 10432}); + Networking::Synapse client("test-nodes-fake-host", 10432); server.start(); client.start(); diff --git a/tests/gtest/test_synapse.cpp b/tests/gtest/test_synapse.cpp index 6720219..a1f718e 100644 --- a/tests/gtest/test_synapse.cpp +++ b/tests/gtest/test_synapse.cpp @@ -28,7 +28,7 @@ TEST(TEST_SYNAPSE, TEST_FAKE_NETWORK) { > server(10435); Networking::Synapse< TestUtils::FakeNetworkController - > client({"test-nodes-fake-host", 10435}); + > client("test-nodes-fake-host", 10435); server.getEventManager().subscribe(onMessageReceived); server.start(); @@ -42,7 +42,7 @@ TEST(TEST_SYNAPSE, TEST_FAKE_NETWORK) { TEST(TEST_SYNAPSE, TEST_GET_SERVER_ID) { Networking::Synapse server(10432); - Networking::Synapse client({"test-nodes-fake-host", 10432}); + Networking::Synapse client("test-nodes-fake-host", 10432); client.getEventManager().subscribe(onMessageReceivedWithUniqueID); server.start(); From 3e52e44058ab2f53630512129b48651ff96178ca Mon Sep 17 00:00:00 2001 From: KbrdDestroyer Date: Mon, 9 Jun 2025 16:03:03 +0300 Subject: [PATCH 38/47] Revert "Migrated SerializedAxonMessage to the rule of 0" This reverts commit 52ab55bdfd3afcf6a342b9e199bb7b06eb9868ee. --- libraries/messages/AxonMessage.cpp | 64 ++++++++++++++++--- libraries/messages/AxonMessage.hpp | 14 +++- .../synapse/utils/SynapseUtility.hpp | 4 +- 3 files changed, 68 insertions(+), 14 deletions(-) diff --git a/libraries/messages/AxonMessage.cpp b/libraries/messages/AxonMessage.cpp index a0d8d18..02c6f71 100644 --- a/libraries/messages/AxonMessage.cpp +++ b/libraries/messages/AxonMessage.cpp @@ -8,24 +8,70 @@ Networking::SerializedAxonMessage::SerializedAxonMessage(const AxonMessage &mess size(message.getSize()) { const TAG_T tag = compressTag(message.getPartID(), message.getFlags(), message.ID()); - const char *buffer = serialize(static_cast(message.getMessage()), message.getSize(), tag, &size); - - bytes = std::shared_ptr( buffer ); + bytes = serialize(static_cast(message.getMessage()), message.getSize(), tag, &size); } Networking::SerializedAxonMessage::SerializedAxonMessage(const char* bits, size64_t actualSize) : size(actualSize) { if (actualSize > 0) { - bytes = std::make_shared(size); - memcpy(const_cast(bytes.get()), bits, size); + bytes = new char[size]; + memcpy(const_cast(bytes), bits, size); + } +} + +Networking::SerializedAxonMessage::SerializedAxonMessage(const SerializedAxonMessage &message) : + size(message.size), + offset(message.offset) +{ + if (size > 0) + { + bytes = new char[size]; + memcpy(const_cast(bytes), message.bytes, size); } } +Networking::SerializedAxonMessage::SerializedAxonMessage(SerializedAxonMessage &&message) noexcept : + size(std::exchange(message.size, 0)), + bytes(std::exchange(message.bytes, nullptr)) +{} + +Networking::SerializedAxonMessage::~SerializedAxonMessage() { + if (bytes && owning) + delete[] bytes; +} + TAG_T Networking::SerializedAxonMessage::compressTag(uint8_t optionalData, uint8_t newFlags, uint16_t id) { return ((optionalData << 8) | newFlags) << 16 | id; } +Networking::SerializedAxonMessage & +Networking::SerializedAxonMessage::operator=(const SerializedAxonMessage &message) { + if (&message == this) + return *this; + + size = message.size; + + if (size > 0) + { + bytes = new char[size]; + memcpy(const_cast(bytes), message.bytes, size); + } + + return * this; +} + +Networking::SerializedAxonMessage & +Networking::SerializedAxonMessage::operator=(SerializedAxonMessage &&message) noexcept { + if (&message == this) + return *this; + + std::exchange(size, message.size); + std::exchange(bytes, message.bytes); + + return * this; +} + #pragma endregion #pragma region AxonMessage @@ -45,16 +91,14 @@ Networking::AxonMessage::AxonMessage(const void* message, size64_t size, uint8_t Networking::AxonMessage::AxonMessage(const SerializedAxonMessage &serialized) { TAG_T tag; - uint8_t _ret = deserialize( - serialized.bytes.get(), + deserialize( + serialized.bytes, serialized.size, &this->message, &this->size, &tag ); - - if (_ret == 0) - decompressTag(tag, &partID, &flags, &this->uniqueID); + decompressTag(tag, &partID, &flags, &this->uniqueID); } Networking::AxonMessage::AxonMessage(const AxonMessage &message, const uint8_t additionalFlags) : diff --git a/libraries/messages/AxonMessage.hpp b/libraries/messages/AxonMessage.hpp index df6abc7..398c968 100644 --- a/libraries/messages/AxonMessage.hpp +++ b/libraries/messages/AxonMessage.hpp @@ -46,17 +46,25 @@ namespace Networking public: SerializedAxonMessage() = delete; SerializedAxonMessage(const char*, size64_t); + SerializedAxonMessage(const SerializedAxonMessage&); explicit SerializedAxonMessage(const AxonMessage&); + SerializedAxonMessage(SerializedAxonMessage&&) noexcept; + + ~SerializedAxonMessage(); WGETTER( size_t getSize() ) { return size; } - WGETTER ( const char* getBits() ) { return bytes.get(); } + WGETTER ( const char* getBits() ) { return bytes; } + + SerializedAxonMessage& operator=(const SerializedAxonMessage&); + SerializedAxonMessage& operator=(SerializedAxonMessage&&) noexcept; protected: static TAG_T compressTag(uint8_t, uint8_t, uint16_t); private: size64_t size = 0; + uint16_t uniqueID = 0; uintptr_t offset = 0; - - std::shared_ptr bytes = nullptr; + bool owning = true; // todo: `uint16_t _refcnt;` or shared_ptr around bytes array + const char* bytes = nullptr; friend class AxonMessage; }; diff --git a/libraries/networking/synapse/utils/SynapseUtility.hpp b/libraries/networking/synapse/utils/SynapseUtility.hpp index beca5d1..715bff7 100644 --- a/libraries/networking/synapse/utils/SynapseUtility.hpp +++ b/libraries/networking/synapse/utils/SynapseUtility.hpp @@ -23,7 +23,9 @@ namespace Networking { }; /** - * Low-level connection info for convenient storage. + * Low-level connection info for convenient storage + * TODO: + * - Research replacement */ struct ConnectionInfo { From 629af6a99753bc6e93880fe5069a9e0d19711dcb Mon Sep 17 00:00:00 2001 From: Keyboard Destroyer Date: Mon, 9 Jun 2025 21:13:49 +0300 Subject: [PATCH 39/47] Removed alloc from cpps --- libraries/messages/AxonMessage.cpp | 104 +++++------------------------ libraries/messages/AxonMessage.hpp | 25 ++----- 2 files changed, 24 insertions(+), 105 deletions(-) diff --git a/libraries/messages/AxonMessage.cpp b/libraries/messages/AxonMessage.cpp index 02c6f71..135bc37 100644 --- a/libraries/messages/AxonMessage.cpp +++ b/libraries/messages/AxonMessage.cpp @@ -8,70 +8,22 @@ Networking::SerializedAxonMessage::SerializedAxonMessage(const AxonMessage &mess size(message.getSize()) { const TAG_T tag = compressTag(message.getPartID(), message.getFlags(), message.ID()); - bytes = serialize(static_cast(message.getMessage()), message.getSize(), tag, &size); + bytes = std::shared_ptr ( serialize(static_cast(message.getMessage()), message.getSize(), tag, &size) ); } Networking::SerializedAxonMessage::SerializedAxonMessage(const char* bits, size64_t actualSize) : size(actualSize) { if (actualSize > 0) { - bytes = new char[size]; - memcpy(const_cast(bytes), bits, size); + bytes = std::shared_ptr ( new char[size] ); + memcpy(bytes.get(), bits, size); } } -Networking::SerializedAxonMessage::SerializedAxonMessage(const SerializedAxonMessage &message) : - size(message.size), - offset(message.offset) -{ - if (size > 0) - { - bytes = new char[size]; - memcpy(const_cast(bytes), message.bytes, size); - } -} - -Networking::SerializedAxonMessage::SerializedAxonMessage(SerializedAxonMessage &&message) noexcept : - size(std::exchange(message.size, 0)), - bytes(std::exchange(message.bytes, nullptr)) -{} - -Networking::SerializedAxonMessage::~SerializedAxonMessage() { - if (bytes && owning) - delete[] bytes; -} - TAG_T Networking::SerializedAxonMessage::compressTag(uint8_t optionalData, uint8_t newFlags, uint16_t id) { return ((optionalData << 8) | newFlags) << 16 | id; } -Networking::SerializedAxonMessage & -Networking::SerializedAxonMessage::operator=(const SerializedAxonMessage &message) { - if (&message == this) - return *this; - - size = message.size; - - if (size > 0) - { - bytes = new char[size]; - memcpy(const_cast(bytes), message.bytes, size); - } - - return * this; -} - -Networking::SerializedAxonMessage & -Networking::SerializedAxonMessage::operator=(SerializedAxonMessage &&message) noexcept { - if (&message == this) - return *this; - - std::exchange(size, message.size); - std::exchange(bytes, message.bytes); - - return * this; -} - #pragma endregion #pragma region AxonMessage @@ -84,20 +36,25 @@ Networking::AxonMessage::AxonMessage(const void* message, size64_t size, uint8_t if (message == nullptr || size == 0) return; - this->message = new char[size]; - memcpy(this->message, message, size); + this->message = std::shared_ptr(new char[size]); + memcpy(this->message.get(), message, size); } Networking::AxonMessage::AxonMessage(const SerializedAxonMessage &serialized) { TAG_T tag; + + void * buffer; + deserialize( - serialized.bytes, + serialized.bytes.get(), serialized.size, - &this->message, + &buffer, &this->size, &tag ); + + message = std::shared_ptr(static_cast(buffer)); decompressTag(tag, &partID, &flags, &this->uniqueID); } @@ -108,36 +65,14 @@ Networking::AxonMessage::AxonMessage(const AxonMessage &message, const uint8_t a addFlag(ACKNOWLEDGE); } -Networking::AxonMessage::AxonMessage(const AxonMessage& message) : - size(message.size), - partID(message.partID), - flags(message.flags), - uniqueID(message.uniqueID) -{ - if (!message.getMessage() || message.size == 0) - return; - - this->message = new char[size]; - memcpy(this->message, message.getMessage(), this->size); -} - -Networking::AxonMessage::AxonMessage(AxonMessage &message, size64_t size, uint8_t partID, uint8_t flags, uint64_t uniqueID, size64_t offset) : +Networking::AxonMessage::AxonMessage(const AxonMessage &message, size64_t size, uint8_t partID, uint8_t flags, uint64_t uniqueID, size64_t offset) : size(size), message(message.message), partID(partID), flags(flags), uniqueID(uniqueID), offset(offset) -{ - message.owning = false; -} - -Networking::AxonMessage::~AxonMessage() -{ - if (this->message && owning) - delete[] static_cast( message ); - message = nullptr; -} +{} Networking::SerializedAxonMessage Networking::AxonMessage::getSerialized() const noexcept { return SerializedAxonMessage(*this); @@ -166,23 +101,18 @@ Networking::AxonMessage::UniqueAxonMessagePtr Networking::AxonMessage::split(con return std::make_unique(*this, left, partID + 1, flags ^ PARTIAL, uniqueID, size); } -void Networking::AxonMessage::append(const Networking::AxonMessage &other) { +void Networking::AxonMessage::append(const AxonMessage &other) { if (!other.getMessage() || other.size == 0 || other.partID != partID + 1) return; char* tempBuffer = new char[other.size + size]; - // assert((uintptr_t) &size < (uintptr_t) tempBuffer || (uintptr_t) &size > (uintptr_t) tempBuffer + other.size + size); - if (message) { memcpy(tempBuffer, getMessage(), size); - if (owning) - delete[] static_cast(message); - message = nullptr; } - memcpy((static_cast(tempBuffer) + size), other.getMessage(), other.size); + memcpy(tempBuffer + size, other.getMessage(), other.size); - message = tempBuffer; + message = std::shared_ptr(tempBuffer); size += other.size; partID = other.partID; } diff --git a/libraries/messages/AxonMessage.hpp b/libraries/messages/AxonMessage.hpp index 398c968..32b4c55 100644 --- a/libraries/messages/AxonMessage.hpp +++ b/libraries/messages/AxonMessage.hpp @@ -46,26 +46,18 @@ namespace Networking public: SerializedAxonMessage() = delete; SerializedAxonMessage(const char*, size64_t); - SerializedAxonMessage(const SerializedAxonMessage&); explicit SerializedAxonMessage(const AxonMessage&); - SerializedAxonMessage(SerializedAxonMessage&&) noexcept; - ~SerializedAxonMessage(); - - WGETTER( size_t getSize() ) { return size; } - WGETTER ( const char* getBits() ) { return bytes; } - - SerializedAxonMessage& operator=(const SerializedAxonMessage&); - SerializedAxonMessage& operator=(SerializedAxonMessage&&) noexcept; + WGETTER ( size_t getSize() ) { return size; } + WGETTER ( const char* getBits() ) { return bytes.get(); } protected: static TAG_T compressTag(uint8_t, uint8_t, uint16_t); private: size64_t size = 0; uint16_t uniqueID = 0; uintptr_t offset = 0; - bool owning = true; // todo: `uint16_t _refcnt;` or shared_ptr around bytes array - const char* bytes = nullptr; + std::shared_ptr bytes = nullptr; friend class AxonMessage; }; @@ -105,18 +97,15 @@ namespace Networking /** * Copy constructor */ - AxonMessage(const AxonMessage &); - AxonMessage(AxonMessage&, size64_t, uint8_t, uint8_t, uint64_t, size64_t); - ~AxonMessage(); + AxonMessage(const AxonMessage &, size64_t, uint8_t, uint8_t, uint64_t, size64_t); WGETTER(SerializedAxonMessage getSerialized()); - WGETTER(void* getMessage()) { return (message) ? static_cast(static_cast(message) + offset) : message; } + WGETTER(void* getMessage()) { return (message.get()) ? static_cast(message.get() + offset) : nullptr; } WGETTER(size64_t getSize()) { return size; } WGETTER(uint16_t ID()) { return uniqueID; } WGETTER(uint8_t getFlags()) { return flags; } WGETTER(uint8_t getPartID()) { return partID; } WGETTER(bool hasFlag(const TAG_FLAGS flag)) { return flags & flag; } - WGETTER(std::bitset<8> getFlagSet()) { return flags; } void setPartID(const uint8_t id) { this->partID = id; } @@ -137,12 +126,12 @@ namespace Networking static void decompressTag(TAG_T, uint8_t*, uint8_t*, uint16_t*); private: size64_t size = 0; - void* message = nullptr; - bool owning = true; uint8_t partID = 0; uint8_t flags = UNDEFINED; size64_t offset = 0; uint16_t uniqueID = generateUniqueID(); + + std::shared_ptr message = nullptr; }; } From 76cd156462d4a204454d5fbdfb5541b542bc407b Mon Sep 17 00:00:00 2001 From: KbrdDestroyer Date: Wed, 11 Jun 2025 16:31:20 +0300 Subject: [PATCH 40/47] Remove deprecated cast --- libraries/messages/AxonMessage.hpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/libraries/messages/AxonMessage.hpp b/libraries/messages/AxonMessage.hpp index 32b4c55..7c89c67 100644 --- a/libraries/messages/AxonMessage.hpp +++ b/libraries/messages/AxonMessage.hpp @@ -54,10 +54,8 @@ namespace Networking static TAG_T compressTag(uint8_t, uint8_t, uint16_t); private: size64_t size = 0; - uint16_t uniqueID = 0; - uintptr_t offset = 0; - std::shared_ptr bytes = nullptr; + friend class AxonMessage; }; @@ -100,7 +98,7 @@ namespace Networking AxonMessage(const AxonMessage &, size64_t, uint8_t, uint8_t, uint64_t, size64_t); WGETTER(SerializedAxonMessage getSerialized()); - WGETTER(void* getMessage()) { return (message.get()) ? static_cast(message.get() + offset) : nullptr; } + WGETTER(void* getMessage()) { return (message.get()) ? (message.get() + offset) : nullptr; } WGETTER(size64_t getSize()) { return size; } WGETTER(uint16_t ID()) { return uniqueID; } WGETTER(uint8_t getFlags()) { return flags; } From 673485be7d066f2e6533d69433e514cea5b93286 Mon Sep 17 00:00:00 2001 From: KbrdDestroyer Date: Wed, 11 Jun 2025 16:35:45 +0300 Subject: [PATCH 41/47] Test assert --- tests/gtest/FakeNetworkController/FakeNetworkController.hpp | 1 - tests/gtest/test_synapse.cpp | 3 +++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/gtest/FakeNetworkController/FakeNetworkController.hpp b/tests/gtest/FakeNetworkController/FakeNetworkController.hpp index 080963b..0eec207 100644 --- a/tests/gtest/FakeNetworkController/FakeNetworkController.hpp +++ b/tests/gtest/FakeNetworkController/FakeNetworkController.hpp @@ -47,7 +47,6 @@ namespace TestUtils { void send(Networking::AxonMessage&) override; void sendTo(Networking::AxonMessage&, const Networking::NetworkNodeInfo&) override; - GETTER Networking::SynapseInterface * owner() const { return owningSynapse; } protected: void sendSerializedTo(const Networking::SerializedAxonMessage&, const Networking::NetworkNodeInfo&) override; diff --git a/tests/gtest/test_synapse.cpp b/tests/gtest/test_synapse.cpp index a1f718e..b864475 100644 --- a/tests/gtest/test_synapse.cpp +++ b/tests/gtest/test_synapse.cpp @@ -15,6 +15,9 @@ namespace { static uint64_t lastTaken = 0; if (!event.getMessage().hasFlag(Networking::NETOBJ_REPL)) return; + + ASSERT_EQ(event.getMessage().getSize(), sizeof(Networking::MessageProcessor::RequestUniqueIDProto)); + Networking::MessageProcessor::RequestUniqueIDProto repl = * static_cast< Networking::MessageProcessor::RequestUniqueIDProto * > ( event.getMessage().getMessage() ); ASSERT_NE( repl.serverSideID, lastTaken ); lastTaken = repl.serverSideID; From 55129e3743550885eb7b663660154f183cdc9dd1 Mon Sep 17 00:00:00 2001 From: KbrdDestroyer Date: Wed, 11 Jun 2025 16:44:02 +0300 Subject: [PATCH 42/47] Should be equal, but I replaced sizeof with strlen --- tests/gtest/test_synapse.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/gtest/test_synapse.cpp b/tests/gtest/test_synapse.cpp index b864475..aeed5cd 100644 --- a/tests/gtest/test_synapse.cpp +++ b/tests/gtest/test_synapse.cpp @@ -37,7 +37,7 @@ TEST(TEST_SYNAPSE, TEST_FAKE_NETWORK) { server.start(); client.start(); - Networking::AxonMessage msg("Hello World!", sizeof("Hello World!")); + Networking::AxonMessage msg("Hello World!", strlen("Hello World!")); client.send(msg); ASSERT_TRUE(hasVisited); hasVisited = false; From c51806fe8d05972f8bc3d874cdc94bb9473f8685 Mon Sep 17 00:00:00 2001 From: KbrdDestroyer Date: Wed, 11 Jun 2025 16:49:51 +0300 Subject: [PATCH 43/47] Should be equal, but I replaced sizeof with strlen --- tests/gtest/test_synapse.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/gtest/test_synapse.cpp b/tests/gtest/test_synapse.cpp index aeed5cd..e62c669 100644 --- a/tests/gtest/test_synapse.cpp +++ b/tests/gtest/test_synapse.cpp @@ -37,7 +37,7 @@ TEST(TEST_SYNAPSE, TEST_FAKE_NETWORK) { server.start(); client.start(); - Networking::AxonMessage msg("Hello World!", strlen("Hello World!")); + Networking::AxonMessage msg("Hello World!", strlen("Hello World!") + 1); client.send(msg); ASSERT_TRUE(hasVisited); hasVisited = false; From 88deef295b0fead781783fb931eaa463968961c0 Mon Sep 17 00:00:00 2001 From: KbrdDestroyer Date: Wed, 11 Jun 2025 16:59:43 +0300 Subject: [PATCH 44/47] Revert "Removed alloc from cpps" This reverts commit 629af6a9 --- libraries/messages/AxonMessage.cpp | 104 ++++++++++++++++++++++++----- libraries/messages/AxonMessage.hpp | 27 ++++++-- 2 files changed, 107 insertions(+), 24 deletions(-) diff --git a/libraries/messages/AxonMessage.cpp b/libraries/messages/AxonMessage.cpp index 135bc37..02c6f71 100644 --- a/libraries/messages/AxonMessage.cpp +++ b/libraries/messages/AxonMessage.cpp @@ -8,22 +8,70 @@ Networking::SerializedAxonMessage::SerializedAxonMessage(const AxonMessage &mess size(message.getSize()) { const TAG_T tag = compressTag(message.getPartID(), message.getFlags(), message.ID()); - bytes = std::shared_ptr ( serialize(static_cast(message.getMessage()), message.getSize(), tag, &size) ); + bytes = serialize(static_cast(message.getMessage()), message.getSize(), tag, &size); } Networking::SerializedAxonMessage::SerializedAxonMessage(const char* bits, size64_t actualSize) : size(actualSize) { if (actualSize > 0) { - bytes = std::shared_ptr ( new char[size] ); - memcpy(bytes.get(), bits, size); + bytes = new char[size]; + memcpy(const_cast(bytes), bits, size); } } +Networking::SerializedAxonMessage::SerializedAxonMessage(const SerializedAxonMessage &message) : + size(message.size), + offset(message.offset) +{ + if (size > 0) + { + bytes = new char[size]; + memcpy(const_cast(bytes), message.bytes, size); + } +} + +Networking::SerializedAxonMessage::SerializedAxonMessage(SerializedAxonMessage &&message) noexcept : + size(std::exchange(message.size, 0)), + bytes(std::exchange(message.bytes, nullptr)) +{} + +Networking::SerializedAxonMessage::~SerializedAxonMessage() { + if (bytes && owning) + delete[] bytes; +} + TAG_T Networking::SerializedAxonMessage::compressTag(uint8_t optionalData, uint8_t newFlags, uint16_t id) { return ((optionalData << 8) | newFlags) << 16 | id; } +Networking::SerializedAxonMessage & +Networking::SerializedAxonMessage::operator=(const SerializedAxonMessage &message) { + if (&message == this) + return *this; + + size = message.size; + + if (size > 0) + { + bytes = new char[size]; + memcpy(const_cast(bytes), message.bytes, size); + } + + return * this; +} + +Networking::SerializedAxonMessage & +Networking::SerializedAxonMessage::operator=(SerializedAxonMessage &&message) noexcept { + if (&message == this) + return *this; + + std::exchange(size, message.size); + std::exchange(bytes, message.bytes); + + return * this; +} + #pragma endregion #pragma region AxonMessage @@ -36,25 +84,20 @@ Networking::AxonMessage::AxonMessage(const void* message, size64_t size, uint8_t if (message == nullptr || size == 0) return; - this->message = std::shared_ptr(new char[size]); - memcpy(this->message.get(), message, size); + this->message = new char[size]; + memcpy(this->message, message, size); } Networking::AxonMessage::AxonMessage(const SerializedAxonMessage &serialized) { TAG_T tag; - - void * buffer; - deserialize( - serialized.bytes.get(), + serialized.bytes, serialized.size, - &buffer, + &this->message, &this->size, &tag ); - - message = std::shared_ptr(static_cast(buffer)); decompressTag(tag, &partID, &flags, &this->uniqueID); } @@ -65,14 +108,36 @@ Networking::AxonMessage::AxonMessage(const AxonMessage &message, const uint8_t a addFlag(ACKNOWLEDGE); } -Networking::AxonMessage::AxonMessage(const AxonMessage &message, size64_t size, uint8_t partID, uint8_t flags, uint64_t uniqueID, size64_t offset) : +Networking::AxonMessage::AxonMessage(const AxonMessage& message) : + size(message.size), + partID(message.partID), + flags(message.flags), + uniqueID(message.uniqueID) +{ + if (!message.getMessage() || message.size == 0) + return; + + this->message = new char[size]; + memcpy(this->message, message.getMessage(), this->size); +} + +Networking::AxonMessage::AxonMessage(AxonMessage &message, size64_t size, uint8_t partID, uint8_t flags, uint64_t uniqueID, size64_t offset) : size(size), message(message.message), partID(partID), flags(flags), uniqueID(uniqueID), offset(offset) -{} +{ + message.owning = false; +} + +Networking::AxonMessage::~AxonMessage() +{ + if (this->message && owning) + delete[] static_cast( message ); + message = nullptr; +} Networking::SerializedAxonMessage Networking::AxonMessage::getSerialized() const noexcept { return SerializedAxonMessage(*this); @@ -101,18 +166,23 @@ Networking::AxonMessage::UniqueAxonMessagePtr Networking::AxonMessage::split(con return std::make_unique(*this, left, partID + 1, flags ^ PARTIAL, uniqueID, size); } -void Networking::AxonMessage::append(const AxonMessage &other) { +void Networking::AxonMessage::append(const Networking::AxonMessage &other) { if (!other.getMessage() || other.size == 0 || other.partID != partID + 1) return; char* tempBuffer = new char[other.size + size]; + // assert((uintptr_t) &size < (uintptr_t) tempBuffer || (uintptr_t) &size > (uintptr_t) tempBuffer + other.size + size); + if (message) { memcpy(tempBuffer, getMessage(), size); + if (owning) + delete[] static_cast(message); + message = nullptr; } - memcpy(tempBuffer + size, other.getMessage(), other.size); + memcpy((static_cast(tempBuffer) + size), other.getMessage(), other.size); - message = std::shared_ptr(tempBuffer); + message = tempBuffer; size += other.size; partID = other.partID; } diff --git a/libraries/messages/AxonMessage.hpp b/libraries/messages/AxonMessage.hpp index 7c89c67..398c968 100644 --- a/libraries/messages/AxonMessage.hpp +++ b/libraries/messages/AxonMessage.hpp @@ -46,15 +46,25 @@ namespace Networking public: SerializedAxonMessage() = delete; SerializedAxonMessage(const char*, size64_t); + SerializedAxonMessage(const SerializedAxonMessage&); explicit SerializedAxonMessage(const AxonMessage&); + SerializedAxonMessage(SerializedAxonMessage&&) noexcept; - WGETTER ( size_t getSize() ) { return size; } - WGETTER ( const char* getBits() ) { return bytes.get(); } + ~SerializedAxonMessage(); + + WGETTER( size_t getSize() ) { return size; } + WGETTER ( const char* getBits() ) { return bytes; } + + SerializedAxonMessage& operator=(const SerializedAxonMessage&); + SerializedAxonMessage& operator=(SerializedAxonMessage&&) noexcept; protected: static TAG_T compressTag(uint8_t, uint8_t, uint16_t); private: size64_t size = 0; - std::shared_ptr bytes = nullptr; + uint16_t uniqueID = 0; + uintptr_t offset = 0; + bool owning = true; // todo: `uint16_t _refcnt;` or shared_ptr around bytes array + const char* bytes = nullptr; friend class AxonMessage; }; @@ -95,15 +105,18 @@ namespace Networking /** * Copy constructor */ - AxonMessage(const AxonMessage &, size64_t, uint8_t, uint8_t, uint64_t, size64_t); + AxonMessage(const AxonMessage &); + AxonMessage(AxonMessage&, size64_t, uint8_t, uint8_t, uint64_t, size64_t); + ~AxonMessage(); WGETTER(SerializedAxonMessage getSerialized()); - WGETTER(void* getMessage()) { return (message.get()) ? (message.get() + offset) : nullptr; } + WGETTER(void* getMessage()) { return (message) ? static_cast(static_cast(message) + offset) : message; } WGETTER(size64_t getSize()) { return size; } WGETTER(uint16_t ID()) { return uniqueID; } WGETTER(uint8_t getFlags()) { return flags; } WGETTER(uint8_t getPartID()) { return partID; } WGETTER(bool hasFlag(const TAG_FLAGS flag)) { return flags & flag; } + WGETTER(std::bitset<8> getFlagSet()) { return flags; } void setPartID(const uint8_t id) { this->partID = id; } @@ -124,12 +137,12 @@ namespace Networking static void decompressTag(TAG_T, uint8_t*, uint8_t*, uint16_t*); private: size64_t size = 0; + void* message = nullptr; + bool owning = true; uint8_t partID = 0; uint8_t flags = UNDEFINED; size64_t offset = 0; uint16_t uniqueID = generateUniqueID(); - - std::shared_ptr message = nullptr; }; } From ce979d55ff434413948bc5422fdc55acb555f558 Mon Sep 17 00:00:00 2001 From: KbrdDestroyer Date: Fri, 13 Jun 2025 11:15:44 +0300 Subject: [PATCH 45/47] Slight changes in AxonMessage protocol before refactoring --- libraries/messages/AxonMessage.cpp | 47 +++++++++++++++--------------- libraries/messages/AxonMessage.hpp | 9 +++--- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/libraries/messages/AxonMessage.cpp b/libraries/messages/AxonMessage.cpp index 02c6f71..40e16c1 100644 --- a/libraries/messages/AxonMessage.cpp +++ b/libraries/messages/AxonMessage.cpp @@ -20,21 +20,15 @@ Networking::SerializedAxonMessage::SerializedAxonMessage(const char* bits, size6 } } -Networking::SerializedAxonMessage::SerializedAxonMessage(const SerializedAxonMessage &message) : - size(message.size), - offset(message.offset) +Networking::SerializedAxonMessage::SerializedAxonMessage(const SerializedAxonMessage &message) { - if (size > 0) - { - bytes = new char[size]; - memcpy(const_cast(bytes), message.bytes, size); - } + this->copy(message); } -Networking::SerializedAxonMessage::SerializedAxonMessage(SerializedAxonMessage &&message) noexcept : - size(std::exchange(message.size, 0)), - bytes(std::exchange(message.bytes, nullptr)) -{} +Networking::SerializedAxonMessage::SerializedAxonMessage(SerializedAxonMessage &&message) noexcept +{ + this->move(message); +} Networking::SerializedAxonMessage::~SerializedAxonMessage() { if (bytes && owning) @@ -50,14 +44,7 @@ Networking::SerializedAxonMessage::operator=(const SerializedAxonMessage &messag if (&message == this) return *this; - size = message.size; - - if (size > 0) - { - bytes = new char[size]; - memcpy(const_cast(bytes), message.bytes, size); - } - + this->copy(message); return * this; } @@ -66,12 +53,24 @@ Networking::SerializedAxonMessage::operator=(SerializedAxonMessage &&message) no if (&message == this) return *this; - std::exchange(size, message.size); - std::exchange(bytes, message.bytes); - + this->move(message); return * this; } +void Networking::SerializedAxonMessage::copy(const Networking::SerializedAxonMessage &message) { + size = message.size; + if (size > 0) + { + bytes = new char[size]; + memcpy(const_cast(bytes), message.bytes, size); + } +} + +void Networking::SerializedAxonMessage::move(Networking::SerializedAxonMessage &message) noexcept { + size = std::exchange(message.size, 0); + bytes = std::exchange(message.bytes, nullptr); +} + #pragma endregion #pragma region AxonMessage @@ -94,7 +93,7 @@ Networking::AxonMessage::AxonMessage(const SerializedAxonMessage &serialized) deserialize( serialized.bytes, serialized.size, - &this->message, + reinterpret_cast(&this->message), &this->size, &tag ); diff --git a/libraries/messages/AxonMessage.hpp b/libraries/messages/AxonMessage.hpp index 398c968..977e036 100644 --- a/libraries/messages/AxonMessage.hpp +++ b/libraries/messages/AxonMessage.hpp @@ -59,10 +59,11 @@ namespace Networking SerializedAxonMessage& operator=(SerializedAxonMessage&&) noexcept; protected: static TAG_T compressTag(uint8_t, uint8_t, uint16_t); + + void copy(const SerializedAxonMessage&); + void move(SerializedAxonMessage&) noexcept; private: size64_t size = 0; - uint16_t uniqueID = 0; - uintptr_t offset = 0; bool owning = true; // todo: `uint16_t _refcnt;` or shared_ptr around bytes array const char* bytes = nullptr; @@ -110,7 +111,7 @@ namespace Networking ~AxonMessage(); WGETTER(SerializedAxonMessage getSerialized()); - WGETTER(void* getMessage()) { return (message) ? static_cast(static_cast(message) + offset) : message; } + WGETTER(void* getMessage()) { return (message) ? message + offset : message; } WGETTER(size64_t getSize()) { return size; } WGETTER(uint16_t ID()) { return uniqueID; } WGETTER(uint8_t getFlags()) { return flags; } @@ -137,7 +138,7 @@ namespace Networking static void decompressTag(TAG_T, uint8_t*, uint8_t*, uint16_t*); private: size64_t size = 0; - void* message = nullptr; + char * message = nullptr; bool owning = true; uint8_t partID = 0; uint8_t flags = UNDEFINED; From b7f4a55713667cf036ea0088dc1f2f8c1e0882be Mon Sep 17 00:00:00 2001 From: Keyboard Destroyer <43577127+kbrddestroyer@users.noreply.github.com> Date: Sat, 14 Jun 2025 14:36:43 +0300 Subject: [PATCH 46/47] Added the rule of 5 to message class (#142) --- libraries/messages/AxonMessage.cpp | 76 ++++++++++++++++++++++++------ libraries/messages/AxonMessage.hpp | 15 +++--- 2 files changed, 68 insertions(+), 23 deletions(-) diff --git a/libraries/messages/AxonMessage.cpp b/libraries/messages/AxonMessage.cpp index 40e16c1..1b47fef 100644 --- a/libraries/messages/AxonMessage.cpp +++ b/libraries/messages/AxonMessage.cpp @@ -31,7 +31,7 @@ Networking::SerializedAxonMessage::SerializedAxonMessage(SerializedAxonMessage & } Networking::SerializedAxonMessage::~SerializedAxonMessage() { - if (bytes && owning) + if (bytes) delete[] bytes; } @@ -120,24 +120,74 @@ Networking::AxonMessage::AxonMessage(const AxonMessage& message) : memcpy(this->message, message.getMessage(), this->size); } -Networking::AxonMessage::AxonMessage(AxonMessage &message, size64_t size, uint8_t partID, uint8_t flags, uint64_t uniqueID, size64_t offset) : +Networking::AxonMessage::AxonMessage(AxonMessage &&other) noexcept : + size(std::exchange(other.size, 0)), + message(std::exchange(other.message, nullptr)), + partID(std::exchange(other.partID, 0)), + flags(std::exchange(other.flags, UNDEFINED)), + uniqueID(std::exchange(other.uniqueID, 0)) +{} + +Networking::AxonMessage::AxonMessage(const AxonMessage &message, size64_t size, uint8_t partID, uint8_t flags, uint64_t uniqueID, size64_t offset) : size(size), - message(message.message), partID(partID), flags(flags), - uniqueID(uniqueID), - offset(offset) + uniqueID(uniqueID) { - message.owning = false; + if (!message.message || size == 0) + return; + + this->message = new char[size]; + memcpy(this->message, message.message + offset, size); } Networking::AxonMessage::~AxonMessage() { - if (this->message && owning) - delete[] static_cast( message ); + if (this->message) + delete[] message; message = nullptr; } +Networking::AxonMessage & Networking::AxonMessage::operator=(const AxonMessage &other) { + if (&other == this) { + return *this; + } + + if (this->message) { + delete[] this->message; + } + + size = other.size; + partID = other.partID; + flags = other.flags; + uniqueID = other.uniqueID; + + if (other.message && other.size > 0) { + message = new char[size]; + memcpy(message, other.message, size); + } + + return *this; +} + +Networking::AxonMessage & Networking::AxonMessage::operator=(AxonMessage &&other) noexcept { + if (&other == this) { + return *this; + } + + if (this->message) { + delete[] message; + } + + size = std::exchange(other.size, 0); + message = std::exchange(other.message, nullptr); + partID = std::exchange(other.partID, 0); + flags = std::exchange(other.flags, UNDEFINED); + uniqueID = std::exchange(other.uniqueID, 0); + + return *this; +} + Networking::SerializedAxonMessage Networking::AxonMessage::getSerialized() const noexcept { return SerializedAxonMessage(*this); } @@ -165,22 +215,18 @@ Networking::AxonMessage::UniqueAxonMessagePtr Networking::AxonMessage::split(con return std::make_unique(*this, left, partID + 1, flags ^ PARTIAL, uniqueID, size); } -void Networking::AxonMessage::append(const Networking::AxonMessage &other) { +void Networking::AxonMessage::append(const AxonMessage &other) { if (!other.getMessage() || other.size == 0 || other.partID != partID + 1) return; char* tempBuffer = new char[other.size + size]; - - // assert((uintptr_t) &size < (uintptr_t) tempBuffer || (uintptr_t) &size > (uintptr_t) tempBuffer + other.size + size); - if (message) { memcpy(tempBuffer, getMessage(), size); - if (owning) - delete[] static_cast(message); + delete[] message; message = nullptr; } - memcpy((static_cast(tempBuffer) + size), other.getMessage(), other.size); + memcpy(tempBuffer + size, other.getMessage(), other.size); message = tempBuffer; size += other.size; partID = other.partID; diff --git a/libraries/messages/AxonMessage.hpp b/libraries/messages/AxonMessage.hpp index 977e036..4faf190 100644 --- a/libraries/messages/AxonMessage.hpp +++ b/libraries/messages/AxonMessage.hpp @@ -64,7 +64,6 @@ namespace Networking void move(SerializedAxonMessage&) noexcept; private: size64_t size = 0; - bool owning = true; // todo: `uint16_t _refcnt;` or shared_ptr around bytes array const char* bytes = nullptr; friend class AxonMessage; @@ -103,15 +102,17 @@ namespace Networking */ AxonMessage(const AxonMessage &message, uint8_t additionalFlags); - /** - * Copy constructor - */ AxonMessage(const AxonMessage &); - AxonMessage(AxonMessage&, size64_t, uint8_t, uint8_t, uint64_t, size64_t); + AxonMessage(AxonMessage &&) noexcept; + + AxonMessage(const AxonMessage&, size64_t, uint8_t, uint8_t, uint64_t, size64_t); ~AxonMessage(); + AxonMessage & operator= (const AxonMessage &); + AxonMessage & operator= (AxonMessage &&) noexcept; + WGETTER(SerializedAxonMessage getSerialized()); - WGETTER(void* getMessage()) { return (message) ? message + offset : message; } + WGETTER(void* getMessage()) { return message; } WGETTER(size64_t getSize()) { return size; } WGETTER(uint16_t ID()) { return uniqueID; } WGETTER(uint8_t getFlags()) { return flags; } @@ -139,10 +140,8 @@ namespace Networking private: size64_t size = 0; char * message = nullptr; - bool owning = true; uint8_t partID = 0; uint8_t flags = UNDEFINED; - size64_t offset = 0; uint16_t uniqueID = generateUniqueID(); }; } From 93f9bd8d5b217edf06add8f33f7e91ea3bb4e5c6 Mon Sep 17 00:00:00 2001 From: Keyboard Destroyer <43577127+kbrddestroyer@users.noreply.github.com> Date: Sat, 14 Jun 2025 18:15:20 +0300 Subject: [PATCH 47/47] Wip/refactor/message refactor (#143) * Added the rule of 5 to message class * Featurebranch patch - add dynamic allocation in test to avoid direct destructor call * Patch test --- tests/gtest/test_serialization.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/tests/gtest/test_serialization.cpp b/tests/gtest/test_serialization.cpp index 9667962..183cc0d 100644 --- a/tests/gtest/test_serialization.cpp +++ b/tests/gtest/test_serialization.cpp @@ -102,23 +102,24 @@ TEST(TEST_SERIALIZATION, TEST_MESSAGE_TAG) { TEST(TEST_SERIALIZATION, TEST_MESSAGE_SPLIT) { const char* message = "Hello World!"; - Networking::AxonMessage message_( const_cast ( message ), strlen(message) + 1, 0); + auto * message_ = new Networking::AxonMessage( const_cast ( message ), strlen(message) + 1, 0); - ASSERT_STREQ(static_cast(message_.getMessage()), "Hello World!"); - Networking::AxonMessage::UniqueAxonMessagePtr ptr = message_.split(5); + ASSERT_STREQ(static_cast(message_->getMessage()), "Hello World!"); + Networking::AxonMessage::UniqueAxonMessagePtr ptr = message_->split(5); ASSERT_TRUE(ptr.get()); ASSERT_EQ(ptr->getSize(), 8); - ASSERT_EQ(message_.getSize(), 5); + ASSERT_EQ(message_->getSize(), 5); - ASSERT_STREQ(static_cast(message_.getMessage()), "Hello World!"); + ASSERT_STREQ(static_cast(message_->getMessage()), "Hello World!"); - ASSERT_TRUE(message_.hasFlag(Networking::PARTIAL)); + ASSERT_TRUE(message_->hasFlag(Networking::PARTIAL)); ASSERT_FALSE(ptr->hasFlag(Networking::PARTIAL)); - ASSERT_EQ(message_.ID(), ptr->ID()); - ASSERT_EQ(message_.getPartID() + 1, ptr->getPartID()); + ASSERT_EQ(message_->ID(), ptr->ID()); + ASSERT_EQ(message_->getPartID() + 1, ptr->getPartID()); + + delete message_; - message_.~AxonMessage(); ASSERT_STREQ(static_cast(ptr->getMessage()), " World!"); }