Added basic UDP handling - only sending from client supported.

This commit is contained in:
2025-11-07 21:55:13 +01:00
parent c7c3b1c54c
commit 5127fe1999
10 changed files with 378 additions and 6 deletions

View File

@@ -8,6 +8,7 @@
#include <columnlynx/common/utils.hpp>
#include <columnlynx/common/panic_handler.hpp>
#include <columnlynx/client/net/tcp/tcp_client.hpp>
#include <columnlynx/client/net/udp/udp_client.hpp>
using asio::ip::tcp;
using namespace ColumnLynx::Utils;
@@ -34,10 +35,15 @@ int main(int argc, char** argv) {
try {
LibSodiumWrapper sodiumWrapper = LibSodiumWrapper();
std::array<uint8_t, 32> aesKey = {0}; // Defualt zeroed state until modified by handshake
uint64_t sessionID = 0;
asio::io_context io;
auto client = std::make_shared<ColumnLynx::Net::TCP::TCPClient>(io, "127.0.0.1", std::to_string(serverPort()), &sodiumWrapper);
auto client = std::make_shared<ColumnLynx::Net::TCP::TCPClient>(io, "127.0.0.1", std::to_string(serverPort()), &sodiumWrapper, &aesKey, &sessionID);
auto udpClient = std::make_shared<ColumnLynx::Net::UDP::UDPClient>(io, "127.0.0.1", std::to_string(serverPort()), &aesKey, &sessionID);
client->start();
udpClient->start();
// Run the IO context in a separate thread
std::thread ioThread([&io]() {
@@ -50,6 +56,16 @@ int main(int argc, char** argv) {
// Client is running
while (!done) {
std::this_thread::sleep_for(std::chrono::milliseconds(100)); // Temp wait
if (client->isHandshakeComplete()) {
// Send a test UDP message every 5 seconds after handshake is complete
static auto lastSendTime = std::chrono::steady_clock::now();
auto now = std::chrono::steady_clock::now();
if (std::chrono::duration_cast<std::chrono::seconds>(now - lastSendTime).count() >= 5) {
udpClient->sendMessage("Hello from UDP client!");
lastSendTime = now;
}
}
}
log("Client shutting down.");
client->disconnect();

View File

@@ -7,11 +7,14 @@
#include <columnlynx/common/utils.hpp>
#include <columnlynx/common/panic_handler.hpp>
#include <columnlynx/server/net/tcp/tcp_server.hpp>
#include <columnlynx/server/net/udp/udp_server.hpp>
#include <columnlynx/common/libsodium_wrapper.hpp>
#include <unordered_set>
using asio::ip::tcp;
using namespace ColumnLynx::Utils;
using namespace ColumnLynx::Net::TCP;
using namespace ColumnLynx::Net::UDP;
int main(int argc, char** argv) {
PanicHandler::init();
@@ -26,6 +29,7 @@ int main(int argc, char** argv) {
asio::io_context io;
auto server = std::make_shared<TCPServer>(io, serverPort(), &sodiumWrapper);
auto udpServer = std::make_shared<UDPServer>(io, serverPort());
// Run the IO context in a separate thread
std::thread ioThread([&io]() {

View File

@@ -0,0 +1,72 @@
// udp_server.cpp - UDP Server for ColumnLynx
// Copyright (C) 2025 DcruBro
// Distributed under the GPLv3 license. See LICENSE for details.
#include <columnlynx/server/net/udp/udp_server.hpp>
#include <columnlynx/common/libsodium_wrapper.hpp>
#include <columnlynx/common/net/session_registry.hpp>
#include <sodium.h>
#include <memory>
namespace ColumnLynx::Net::UDP {
void UDPServer::mStartReceive() {
mSocket.async_receive_from(
asio::buffer(mRecvBuffer), mRemoteEndpoint,
[this](asio::error_code ec, std::size_t bytes) {
if (!ec && bytes > 0) {
mHandlePacket(bytes);
}
mStartReceive(); // Continue receiving
}
);
}
void UDPServer::mHandlePacket(std::size_t bytes) {
if (bytes < sizeof(UDPPacketHeader))
return;
const auto* hdr = reinterpret_cast<UDPPacketHeader*>(mRecvBuffer.data());
// Get plaintext session ID (assuming first 8 bytes after nonce (header))
uint64_t sessionID = 0;
std::memcpy(&sessionID, mRecvBuffer.data() + sizeof(UDPPacketHeader), sizeof(uint64_t));
auto it = mRecvBuffer.begin() + sizeof(UDPPacketHeader) + sizeof(uint64_t);
std::vector<uint8_t> encryptedPayload(it, mRecvBuffer.begin() + bytes);
// Get associated session state
std::shared_ptr<const SessionState> session = SessionRegistry::getInstance().get(sessionID);
if (!session) {
Utils::warn("UDP: Unknown or invalid session from " + mRemoteEndpoint.address().to_string());
return;
}
// Decrypt the actual payload
try {
auto plaintext = Utils::LibSodiumWrapper::decryptMessage(
encryptedPayload.data(), encryptedPayload.size(),
session->aesKey,
hdr->nonce,
"udp-data"
);
const_cast<SessionState*>(session.get())->setUDPEndpoint(mRemoteEndpoint); // Update endpoint after confirming decryption
// Update recv counter
const_cast<SessionState*>(session.get())->recv_ctr.fetch_add(1, std::memory_order_relaxed);
// TODO: Process the packet payload
// For now, just log the decrypted payload
std::string payloadStr(plaintext.begin(), plaintext.end());
Utils::log("UDP: Received packet from " + mRemoteEndpoint.address().to_string() + " - Payload: " + payloadStr);
} catch (...) {
Utils::warn("UDP: Failed to decrypt payload from " + mRemoteEndpoint.address().to_string());
return;
}
}
void UDPServer::mSendData(const uint64_t sessionID, const std::string& data) {
// TODO: Implement
}
}