feat: Added simple UDP Data Provider

This commit is contained in:
WerWolv
2025-05-29 18:00:29 +02:00
parent ac67e985af
commit 03884ddd05
8 changed files with 319 additions and 0 deletions

View File

@@ -41,6 +41,7 @@ set(LIBIMHEX_SOURCES
source/helpers/semantic_version.cpp
source/helpers/keys.cpp
source/helpers/freetype.cpp
source/helpers/udp_server.cpp
source/test/tests.cpp

View File

@@ -0,0 +1,58 @@
#pragma once
#include <hex.hpp>
#include <functional>
#include <thread>
#include <atomic>
namespace hex {
class UDPServer {
public:
using Callback = std::function<void(std::span<const u8> data)>;
UDPServer() = default;
UDPServer(u16 port, Callback callback);
~UDPServer();
UDPServer(const UDPServer&) = delete;
UDPServer& operator=(const UDPServer&) = delete;
UDPServer(UDPServer &&other) noexcept {
m_port = other.m_port;
m_callback = std::move(other.m_callback);
m_thread = std::move(other.m_thread);
m_running = other.m_running.load();
other.m_running = false;
m_socketFd = other.m_socketFd;
other.m_socketFd = -1;
}
UDPServer& operator=(UDPServer &&other) noexcept {
if (this != &other) {
m_port = other.m_port;
m_callback = std::move(other.m_callback);
m_thread = std::move(other.m_thread);
m_running = other.m_running.load();
other.m_running = false;
m_socketFd = other.m_socketFd;
other.m_socketFd = -1;
}
return *this;
}
void start();
void stop();
[[nodiscard]] u16 getPort() const { return m_port; }
private:
void run();
u16 m_port;
Callback m_callback;
std::thread m_thread;
std::atomic<bool> m_running;
int m_socketFd;
};
}

View File

@@ -0,0 +1,69 @@
#include <hex/helpers/udp_server.hpp>
#if defined(OS_WINDOWS)
#include <winsock2.h>
#include <ws2tcpip.h>
using socklen_t = int;
#else
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#endif
namespace hex {
UDPServer::UDPServer(u16 port, Callback callback)
: m_port(port), m_callback(std::move(callback)), m_running(false), m_socketFd(-1) {
}
UDPServer::~UDPServer() {
stop();
}
void UDPServer::start() {
m_running = true;
m_thread = std::thread(&UDPServer::run, this);
}
void UDPServer::stop() {
m_running = false;
if (m_thread.joinable()) m_thread.join();
if (m_socketFd >= 0) {
#if defined(OS_WINDOWS)
::closesocket(m_socketFd);
#else
::close(sockfd_);
#endif
}
}
void UDPServer::run() {
m_socketFd = ::socket(AF_INET, SOCK_DGRAM, 0);
if (m_socketFd < 0) {
return;
}
sockaddr_in addr = { };
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(m_port);
if (bind(m_socketFd, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) < 0) {
return;
}
std::vector<u8> buffer(64 * 1024, 0x00);
while (m_running) {
sockaddr_in client{};
socklen_t len = sizeof(client);
const auto bytes = ::recvfrom(m_socketFd, reinterpret_cast<char*>(buffer.data()), buffer.size(), 0, reinterpret_cast<sockaddr*>(&client), &len);
if (bytes > 0) {
buffer[bytes] = '\0';
m_callback({ buffer.data(), buffer.data() + bytes });
}
}
}
}