Comment some code

This commit is contained in:
2025-11-26 21:52:01 +01:00
parent 84c00b7bcb
commit d2242ebbc7
12 changed files with 174 additions and 106 deletions

View File

@@ -63,17 +63,26 @@ namespace ColumnLynx::Net::TCP {
} }
} }
// Starts the TCP Client and initiaties the handshake
void start(); void start();
// Sends a TCP message to the server
void sendMessage(ClientMessageType type, const std::string& data = ""); void sendMessage(ClientMessageType type, const std::string& data = "");
// Attempt to gracefully disconnect from the server
void disconnect(bool echo = true); void disconnect(bool echo = true);
// Get the handshake status
bool isHandshakeComplete() const; bool isHandshakeComplete() const;
// Get the connection status
bool isConnected() const; bool isConnected() const;
private: private:
// Start the heartbeat routine
void mStartHeartbeat(); void mStartHeartbeat();
// Handle an incoming TCP message
void mHandleMessage(ServerMessageType type, const std::string& data); void mHandleMessage(ServerMessageType type, const std::string& data);
// TODO: Move ptrs to smart ptrs
bool mConnected = false; bool mConnected = false;
bool mHandshakeComplete = false; bool mHandshakeComplete = false;
tcp::resolver mResolver; tcp::resolver mResolver;

View File

@@ -25,12 +25,17 @@ namespace ColumnLynx::Net::UDP {
mStartReceive(); mStartReceive();
} }
// Start the UDP client
void start(); void start();
// Send a UDP message
void sendMessage(const std::string& data = ""); void sendMessage(const std::string& data = "");
// Stop the UDP client
void stop(); void stop();
private: private:
// Start the UDP listener routine
void mStartReceive(); void mStartReceive();
// Handle an incoming UDP message
void mHandlePacket(std::size_t bytes); void mHandlePacket(std::size_t bytes);
asio::ip::udp::socket mSocket; asio::ip::udp::socket mSocket;

View File

@@ -35,12 +35,14 @@ namespace ColumnLynx::Utils {
public: public:
LibSodiumWrapper(); LibSodiumWrapper();
// These are pretty self-explanatory
uint8_t* getPublicKey(); uint8_t* getPublicKey();
uint8_t* getPrivateKey(); uint8_t* getPrivateKey();
uint8_t* getXPublicKey() { return mXPublicKey.data(); } uint8_t* getXPublicKey() { return mXPublicKey.data(); }
uint8_t* getXPrivateKey() { return mXPrivateKey.data(); } uint8_t* getXPrivateKey() { return mXPrivateKey.data(); }
// Dangerous! // Set the Asymmetric signing keypair. This also regenerates the corresponding encryption keypair; Dangerous!
void setKeys(PublicKey pk, PrivateKey sk) { void setKeys(PublicKey pk, PrivateKey sk) {
mPublicKey = pk; mPublicKey = pk;
mPrivateKey = sk; mPrivateKey = sk;
@@ -54,18 +56,14 @@ namespace ColumnLynx::Utils {
// Generates a random 256-bit (32-byte) array // Generates a random 256-bit (32-byte) array
static std::array<uint8_t, 32> generateRandom256Bit(); static std::array<uint8_t, 32> generateRandom256Bit();
// Sign a message with the stored private key
static inline Signature signMessage(const uint8_t* msg, size_t len, const PrivateKey& sk) { static inline Signature signMessage(const uint8_t* msg, size_t len, const PrivateKey& sk) {
Signature sig{}; Signature sig{};
crypto_sign_detached(sig.data(), nullptr, msg, len, sk.data()); crypto_sign_detached(sig.data(), nullptr, msg, len, sk.data());
return sig; return sig;
} }
static inline bool verifyMessage(const uint8_t* msg, size_t len,
const Signature& sig, const PublicKey& pk) {
return crypto_sign_verify_detached(sig.data(), msg, len, pk.data()) == 0;
}
// Overloads for std::string / std::array // Overloads for std::string / std::array
static inline Signature signMessage(const std::string& msg, const PrivateKey& sk) { static inline Signature signMessage(const std::string& msg, const PrivateKey& sk) {
return signMessage(reinterpret_cast<const uint8_t*>(msg.data()), msg.size(), sk); return signMessage(reinterpret_cast<const uint8_t*>(msg.data()), msg.size(), sk);
@@ -82,6 +80,11 @@ namespace ColumnLynx::Utils {
return sig; return sig;
} }
// Verify a message with a given public key
static inline bool verifyMessage(const uint8_t* msg, size_t len, const Signature& sig, const PublicKey& pk) {
return crypto_sign_verify_detached(sig.data(), msg, len, pk.data()) == 0;
}
static inline bool verifyMessage(const std::string& msg, const Signature& sig, const PublicKey& pk) { static inline bool verifyMessage(const std::string& msg, const Signature& sig, const PublicKey& pk) {
return verifyMessage(reinterpret_cast<const uint8_t*>(msg.data()), msg.size(), sig, pk); return verifyMessage(reinterpret_cast<const uint8_t*>(msg.data()), msg.size(), sig, pk);
} }
@@ -96,7 +99,7 @@ namespace ColumnLynx::Utils {
return crypto_sign_verify_detached(sig.data(), msg, len, pk_raw) == 0; return crypto_sign_verify_detached(sig.data(), msg, len, pk_raw) == 0;
} }
// Encrypt with ChaCha20-Poly1305 (returns ciphertext as bytes) // Encrypt symmetrically with ChaCha20-Poly1305; returns ciphertext as bytes
static inline std::vector<uint8_t> encryptMessage( static inline std::vector<uint8_t> encryptMessage(
const uint8_t* plaintext, size_t len, const uint8_t* plaintext, size_t len,
const SymmetricKey& key, const Nonce& nonce, const SymmetricKey& key, const Nonce& nonce,
@@ -119,7 +122,7 @@ namespace ColumnLynx::Utils {
return ciphertext; return ciphertext;
} }
// Decrypt with ChaCha20-Poly1305 (returns plaintext as bytes) // Decrypt symmetrically with ChaCha20-Poly1305; Returns plaintext as bytes
static inline std::vector<uint8_t> decryptMessage( static inline std::vector<uint8_t> decryptMessage(
const uint8_t* ciphertext, size_t len, const uint8_t* ciphertext, size_t len,
const SymmetricKey& key, const Nonce& nonce, const SymmetricKey& key, const Nonce& nonce,
@@ -145,12 +148,14 @@ namespace ColumnLynx::Utils {
return plaintext; return plaintext;
} }
// Returns a random nonce
static inline Nonce generateNonce() { static inline Nonce generateNonce() {
Nonce n{}; Nonce n{};
randombytes_buf(n.data(), n.size()); randombytes_buf(n.data(), n.size());
return n; return n;
} }
// Encrypt message asymmetrically; Returns ciphertext as bytes
static inline std::vector<uint8_t> encryptAsymmetric( static inline std::vector<uint8_t> encryptAsymmetric(
const uint8_t* plaintext, size_t len, const uint8_t* plaintext, size_t len,
const AsymNonce& nonce, const AsymNonce& nonce,
@@ -171,6 +176,7 @@ namespace ColumnLynx::Utils {
return ciphertext; return ciphertext;
} }
// Decrypt message asymmetrically; Returns plaintext as bytes
static inline std::vector<uint8_t> decryptAsymmetric( static inline std::vector<uint8_t> decryptAsymmetric(
const uint8_t* ciphertext, size_t len, const uint8_t* ciphertext, size_t len,
const AsymNonce& nonce, const AsymNonce& nonce,
@@ -194,97 +200,99 @@ namespace ColumnLynx::Utils {
return plaintext; return plaintext;
} }
static inline bool verifyCertificateWithSystemCAs(const std::vector<uint8_t>& cert_der) { // Verify a public key (certificate) against system-installed CAs
// Parse DER-encoded certificate static inline bool verifyCertificateWithSystemCAs(const std::vector<uint8_t>& cert_der) {
const unsigned char* p = cert_der.data(); // Parse DER-encoded certificate
std::unique_ptr<X509, decltype(&X509_free)> cert( const unsigned char* p = cert_der.data();
d2i_X509(nullptr, &p, cert_der.size()), X509_free std::unique_ptr<X509, decltype(&X509_free)> cert(
); d2i_X509(nullptr, &p, cert_der.size()), X509_free
if (!cert) { );
return false; if (!cert) {
return false;
}
// Create a certificate store
std::unique_ptr<X509_STORE, decltype(&X509_STORE_free)> store(
X509_STORE_new(), X509_STORE_free
);
if (!store) {
return false;
}
// Load system default CA paths (/etc/ssl/certs, etc.)
if (X509_STORE_set_default_paths(store.get()) != 1) {
return false;
}
// Create a verification context
std::unique_ptr<X509_STORE_CTX, decltype(&X509_STORE_CTX_free)> ctx(
X509_STORE_CTX_new(), X509_STORE_CTX_free
);
if (!ctx) {
return false;
}
// Initialize verification context
if (X509_STORE_CTX_init(ctx.get(), store.get(), cert.get(), nullptr) != 1) {
return false;
}
// Perform the actual certificate verification
int result = X509_verify_cert(ctx.get());
return result == 1;
} }
// Create a certificate store
std::unique_ptr<X509_STORE, decltype(&X509_STORE_free)> store(
X509_STORE_new(), X509_STORE_free
);
if (!store) {
return false;
}
// Load system default CA paths (/etc/ssl/certs, etc.)
if (X509_STORE_set_default_paths(store.get()) != 1) {
return false;
}
// Create a verification context
std::unique_ptr<X509_STORE_CTX, decltype(&X509_STORE_CTX_free)> ctx(
X509_STORE_CTX_new(), X509_STORE_CTX_free
);
if (!ctx) {
return false;
}
// Initialize verification context
if (X509_STORE_CTX_init(ctx.get(), store.get(), cert.get(), nullptr) != 1) {
return false;
}
// Perform the actual certificate verification
int result = X509_verify_cert(ctx.get());
return result == 1;
}
static inline std::vector<std::string> getCertificateHostname(const std::vector<uint8_t>& cert_der) { // Extract the hostnames (Subject Alternative Names and Common Names) out of a public key (certificate)
std::vector<std::string> names; static inline std::vector<std::string> getCertificateHostname(const std::vector<uint8_t>& cert_der) {
std::vector<std::string> names;
if (cert_der.empty()) if (cert_der.empty())
return names; return names;
// Parse DER certificate // Parse DER certificate
const unsigned char* p = cert_der.data(); const unsigned char* p = cert_der.data();
X509* cert = d2i_X509(nullptr, &p, cert_der.size()); X509* cert = d2i_X509(nullptr, &p, cert_der.size());
if (!cert) if (!cert)
return names; return names;
// --- Subject Alternative Names (SAN) --- // --- Subject Alternative Names (SAN) ---
GENERAL_NAMES* san_names = GENERAL_NAMES* san_names =
(GENERAL_NAMES*)X509_get_ext_d2i(cert, NID_subject_alt_name, nullptr, nullptr); (GENERAL_NAMES*)X509_get_ext_d2i(cert, NID_subject_alt_name, nullptr, nullptr);
if (san_names) { if (san_names) {
int san_count = sk_GENERAL_NAME_num(san_names); int san_count = sk_GENERAL_NAME_num(san_names);
for (int i = 0; i < san_count; i++) { for (int i = 0; i < san_count; i++) {
const GENERAL_NAME* current = sk_GENERAL_NAME_value(san_names, i); const GENERAL_NAME* current = sk_GENERAL_NAME_value(san_names, i);
if (current->type == GEN_DNS) { if (current->type == GEN_DNS) {
const char* dns_name = (const char*)ASN1_STRING_get0_data(current->d.dNSName); const char* dns_name = (const char*)ASN1_STRING_get0_data(current->d.dNSName);
// Safety: ensure no embedded nulls // Safety: ensure no embedded nulls
if (ASN1_STRING_length(current->d.dNSName) == (int)std::strlen(dns_name)) { if (ASN1_STRING_length(current->d.dNSName) == (int)std::strlen(dns_name)) {
names.emplace_back(dns_name); names.emplace_back(dns_name);
}
}
}
GENERAL_NAMES_free(san_names);
}
// --- Fallback: Common Name (CN) ---
if (names.empty()) {
X509_NAME* subject = X509_get_subject_name(cert);
if (subject) {
int idx = X509_NAME_get_index_by_NID(subject, NID_commonName, -1);
if (idx >= 0) {
X509_NAME_ENTRY* entry = X509_NAME_get_entry(subject, idx);
ASN1_STRING* cn_asn1 = X509_NAME_ENTRY_get_data(entry);
const char* cn_str = (const char*)ASN1_STRING_get0_data(cn_asn1);
if (ASN1_STRING_length(cn_asn1) == (int)std::strlen(cn_str)) {
names.emplace_back(cn_str);
}
} }
} }
} }
GENERAL_NAMES_free(san_names);
X509_free(cert);
return names;
} }
// --- Fallback: Common Name (CN) ---
if (names.empty()) {
X509_NAME* subject = X509_get_subject_name(cert);
if (subject) {
int idx = X509_NAME_get_index_by_NID(subject, NID_commonName, -1);
if (idx >= 0) {
X509_NAME_ENTRY* entry = X509_NAME_get_entry(subject, idx);
ASN1_STRING* cn_asn1 = X509_NAME_ENTRY_get_data(entry);
const char* cn_str = (const char*)ASN1_STRING_get0_data(cn_asn1);
if (ASN1_STRING_length(cn_asn1) == (int)std::strlen(cn_str)) {
names.emplace_back(cn_str);
}
}
}
}
X509_free(cert);
return names;
}
private: private:
std::array<uint8_t, crypto_sign_PUBLICKEYBYTES> mPublicKey; std::array<uint8_t, crypto_sign_PUBLICKEYBYTES> mPublicKey;

View File

@@ -14,16 +14,16 @@
namespace ColumnLynx::Net { namespace ColumnLynx::Net {
struct SessionState { struct SessionState {
SymmetricKey aesKey; // Immutable after creation SymmetricKey aesKey; // Agreed-upon AES-256 kes for that session; Immutable after creation
std::atomic<uint64_t> send_ctr{0}; // Per-direction counters std::atomic<uint64_t> send_ctr{0}; // Per-direction counters
std::atomic<uint64_t> recv_ctr{0}; std::atomic<uint64_t> recv_ctr{0}; // Per-direction counters
asio::ip::udp::endpoint udpEndpoint; asio::ip::udp::endpoint udpEndpoint; // Deducted IP + Port of that session client
std::atomic<uint64_t> sendCounter{0}; std::atomic<uint64_t> sendCounter{0}; // Counter of sent messages
std::chrono::steady_clock::time_point created = std::chrono::steady_clock::now(); std::chrono::steady_clock::time_point created = std::chrono::steady_clock::now(); // Time created
std::chrono::steady_clock::time_point expires{}; std::chrono::steady_clock::time_point expires{}; // Time of expiry
uint32_t clientTunIP; uint32_t clientTunIP; // Assigned IP
uint32_t serverTunIP; uint32_t serverTunIP; // Server IP
uint64_t sessionID; uint64_t sessionID; // Session ID
Nonce base_nonce{}; Nonce base_nonce{};
~SessionState() { sodium_memzero(aesKey.data(), aesKey.size()); } ~SessionState() { sodium_memzero(aesKey.data(), aesKey.size()); }
@@ -36,6 +36,7 @@ namespace ColumnLynx::Net {
expires = created + ttl; expires = created + ttl;
} }
// Set the UDP endpoint
void setUDPEndpoint(const asio::ip::udp::endpoint& ep) { void setUDPEndpoint(const asio::ip::udp::endpoint& ep) {
udpEndpoint = ep; udpEndpoint = ep;
} }
@@ -43,28 +44,31 @@ namespace ColumnLynx::Net {
class SessionRegistry { class SessionRegistry {
public: public:
// Return a reference to the Session Registry instance
static SessionRegistry& getInstance() { static SessionRegistry instance; return instance; } static SessionRegistry& getInstance() { static SessionRegistry instance; return instance; }
// Insert or replace // Insert or replace a session entry
void put(uint64_t sessionID, std::shared_ptr<SessionState> state) { void put(uint64_t sessionID, std::shared_ptr<SessionState> state) {
std::unique_lock lock(mMutex); std::unique_lock lock(mMutex);
mSessions[sessionID] = std::move(state); mSessions[sessionID] = std::move(state);
mIPSessions[mSessions[sessionID]->clientTunIP] = mSessions[sessionID]; mIPSessions[mSessions[sessionID]->clientTunIP] = mSessions[sessionID];
} }
// Lookup // Lookup a session entry by session ID
std::shared_ptr<const SessionState> get(uint64_t sessionID) const { std::shared_ptr<const SessionState> get(uint64_t sessionID) const {
std::shared_lock lock(mMutex); std::shared_lock lock(mMutex);
auto it = mSessions.find(sessionID); auto it = mSessions.find(sessionID);
return (it == mSessions.end()) ? nullptr : it->second; return (it == mSessions.end()) ? nullptr : it->second;
} }
// Lookup a session entry by IPv4
std::shared_ptr<const SessionState> getByIP(uint32_t ip) const { std::shared_ptr<const SessionState> getByIP(uint32_t ip) const {
std::shared_lock lock(mMutex); std::shared_lock lock(mMutex);
auto it = mIPSessions.find(ip); auto it = mIPSessions.find(ip);
return (it == mIPSessions.end()) ? nullptr : it->second; return (it == mIPSessions.end()) ? nullptr : it->second;
} }
// Get a snapshot of the Session Registry
std::unordered_map<uint64_t, std::shared_ptr<SessionState>> snapshot() const { std::unordered_map<uint64_t, std::shared_ptr<SessionState>> snapshot() const {
std::unordered_map<uint64_t, std::shared_ptr<SessionState>> snap; std::unordered_map<uint64_t, std::shared_ptr<SessionState>> snap;
std::shared_lock lock(mMutex); std::shared_lock lock(mMutex);
@@ -72,7 +76,7 @@ namespace ColumnLynx::Net {
return snap; return snap;
} }
// Remove // Remove a session by ID
void erase(uint64_t sessionID) { void erase(uint64_t sessionID) {
std::unique_lock lock(mMutex); std::unique_lock lock(mMutex);
mSessions.erase(sessionID); mSessions.erase(sessionID);
@@ -99,6 +103,7 @@ namespace ColumnLynx::Net {
} }
} }
// Get the number of registered sessions
int size() const { int size() const {
std::shared_lock lock(mMutex); std::shared_lock lock(mMutex);
return static_cast<int>(mSessions.size()); return static_cast<int>(mSessions.size());
@@ -106,6 +111,7 @@ namespace ColumnLynx::Net {
// IP management (simple for /24 subnet) // IP management (simple for /24 subnet)
// Get the lowest available IPv4 address; Returns 0 if none available
uint32_t getFirstAvailableIP() const { uint32_t getFirstAvailableIP() const {
std::shared_lock lock(mMutex); std::shared_lock lock(mMutex);
uint32_t baseIP = 0x0A0A0002; // 10.10.0.2 uint32_t baseIP = 0x0A0A0002; // 10.10.0.2
@@ -115,15 +121,19 @@ namespace ColumnLynx::Net {
uint32_t candidateIP = baseIP + offset; uint32_t candidateIP = baseIP + offset;
if (mSessionIPs.find(candidateIP) == mSessionIPs.end()) { if (mSessionIPs.find(candidateIP) == mSessionIPs.end()) {
return candidateIP; return candidateIP;
} }
return 0; // Unavailable
} }
} }
// Lock an IP as assigned to a specific session
void lockIP(uint64_t sessionID, uint32_t ip) { void lockIP(uint64_t sessionID, uint32_t ip) {
std::unique_lock lock(mMutex); std::unique_lock lock(mMutex);
mSessionIPs[sessionID] = ip; mSessionIPs[sessionID] = ip;
} }
// Unlock the IP associated with a given session
void deallocIP(uint64_t sessionID) { void deallocIP(uint64_t sessionID) {
std::unique_lock lock(mMutex); std::unique_lock lock(mMutex);
mSessionIPs.erase(sessionID); mSessionIPs.erase(sessionID);

View File

@@ -9,6 +9,7 @@
#include <array> #include <array>
namespace ColumnLynx::Net::UDP { namespace ColumnLynx::Net::UDP {
// @deprecated
// Shared between server and client // Shared between server and client
enum class MessageType : uint8_t { enum class MessageType : uint8_t {
PING = 0x01, PING = 0x01,

View File

@@ -184,7 +184,7 @@ namespace ColumnLynx::Utils {
out << "----------------------\n"; out << "----------------------\n";
} }
//Panic the main thread and instantly halt execution. This produces a stack trace dump. Do not use by itself, throw an error instead. // Panic the main thread and instantly halt execution. This produces a stack trace dump. Do not use by itself, throw an error instead.
static void panic(const std::string& reason) { static void panic(const std::string& reason) {
std::cerr << "\n***\033[31m MAIN THREAD PANIC! \033[0m***\n"; std::cerr << "\n***\033[31m MAIN THREAD PANIC! \033[0m***\n";
std::cerr << "Reason: " << reason << "\n"; std::cerr << "Reason: " << reason << "\n";
@@ -204,6 +204,7 @@ namespace ColumnLynx::Utils {
std::cerr << "Panic trace written to panic_dump.txt\n"; std::cerr << "Panic trace written to panic_dump.txt\n";
} }
// Gets the current time
static std::string currentTime() { static std::string currentTime() {
std::time_t t = std::time(nullptr); std::time_t t = std::time(nullptr);
char buf[64]; char buf[64];

View File

@@ -23,12 +23,18 @@
#endif #endif
namespace ColumnLynx::Utils { namespace ColumnLynx::Utils {
// General log function. Use for logging important information.
void log(const std::string &msg); void log(const std::string &msg);
// General warning function. Use for logging important warnings.
void warn(const std::string &msg); void warn(const std::string &msg);
// General error function. Use for logging failures and general errors.
void error(const std::string &msg); void error(const std::string &msg);
// Debug log function. Use for logging non-important information. These will not print unless the binary is compiled with DEBUG=1
void debug(const std::string &msg); void debug(const std::string &msg);
// Returns the hostname of the running platform.
std::string getHostname(); std::string getHostname();
// Returns the version of the running release.
std::string getVersion(); std::string getVersion();
unsigned short serverPort(); unsigned short serverPort();
unsigned char protocolVersion(); unsigned char protocolVersion();
@@ -36,6 +42,7 @@ namespace ColumnLynx::Utils {
// Raw byte to hex string conversion helper // Raw byte to hex string conversion helper
std::string bytesToHexString(const uint8_t* bytes, size_t length); std::string bytesToHexString(const uint8_t* bytes, size_t length);
// Hex string to raw byte conversion helper
std::vector<uint8_t> hexStringToBytes(const std::string& hex); std::vector<uint8_t> hexStringToBytes(const std::string& hex);
// uint8_t to raw string conversion helper // uint8_t to raw string conversion helper
@@ -59,12 +66,14 @@ namespace ColumnLynx::Utils {
((x & 0xFF00000000000000ULL) >> 56); ((x & 0xFF00000000000000ULL) >> 56);
} }
// host -> big-endian (for little-endian hosts) - 64 bit
inline constexpr uint64_t chtobe64(uint64_t x) { inline constexpr uint64_t chtobe64(uint64_t x) {
return cbswap64(x); // host -> big-endian (for little-endian hosts) return cbswap64(x);
} }
// big-endian -> host (for little-endian hosts) - 64 bit
inline constexpr uint64_t cbe64toh(uint64_t x) { inline constexpr uint64_t cbe64toh(uint64_t x) {
return cbswap64(x); // big-endian -> host (for little-endian hosts) return cbswap64(x);
} }
// Returns the config file in an unordered_map format. This purely reads the config file, you still need to parse it manually. // Returns the config file in an unordered_map format. This purely reads the config file, you still need to parse it manually.

View File

@@ -33,12 +33,18 @@ namespace ColumnLynx::Net::TCP {
return conn; return conn;
} }
// Start a TCP Connection (Handler for an incoming connection)
void start(); void start();
// Send a message to the TCP client
void sendMessage(ServerMessageType type, const std::string& data = ""); void sendMessage(ServerMessageType type, const std::string& data = "");
// Set callback for disconnects
void setDisconnectCallback(std::function<void(std::shared_ptr<TCPConnection>)> cb); void setDisconnectCallback(std::function<void(std::shared_ptr<TCPConnection>)> cb);
// Disconnect the client
void disconnect(); void disconnect();
// Get the assigned session ID
uint64_t getSessionID() const; uint64_t getSessionID() const;
// Get the assigned AES key; You should probably access this via the Session Registry instead
std::array<uint8_t, 32> getAESKey() const; std::array<uint8_t, 32> getAESKey() const;
private: private:
@@ -51,7 +57,9 @@ namespace ColumnLynx::Net::TCP {
mLastHeartbeatSent(std::chrono::steady_clock::now()) mLastHeartbeatSent(std::chrono::steady_clock::now())
{} {}
// Start the heartbeat routine
void mStartHeartbeat(); void mStartHeartbeat();
// Handle an incoming TCP message
void mHandleMessage(ClientMessageType type, const std::string& data); void mHandleMessage(ClientMessageType type, const std::string& data);
std::shared_ptr<MessageHandler> mHandler; std::shared_ptr<MessageHandler> mHandler;

View File

@@ -62,10 +62,13 @@ namespace ColumnLynx::Net::TCP {
mStartAccept(); mStartAccept();
} }
// Stop the TCP Server
void stop(); void stop();
private: private:
// Start accepting clients via TCP
void mStartAccept(); void mStartAccept();
asio::io_context &mIoContext; asio::io_context &mIoContext;
asio::ip::tcp::acceptor mAcceptor; asio::ip::tcp::acceptor mAcceptor;
std::unordered_set<TCPConnection::pointer> mClients; std::unordered_set<TCPConnection::pointer> mClients;

View File

@@ -42,13 +42,18 @@ namespace ColumnLynx::Net::UDP {
mStartReceive(); mStartReceive();
} }
// Stop the UDP server
void stop(); void stop();
// Send UDP data to an endpoint; Fetched via the Session Registry
void sendData(const uint64_t sessionID, const std::string& data); void sendData(const uint64_t sessionID, const std::string& data);
private: private:
// Start receiving UDP data
void mStartReceive(); void mStartReceive();
// Handle an incoming UDP packet
void mHandlePacket(std::size_t bytes); void mHandlePacket(std::size_t bytes);
asio::ip::udp::socket mSocket; asio::ip::udp::socket mSocket;
asio::ip::udp::endpoint mRemoteEndpoint; asio::ip::udp::endpoint mRemoteEndpoint;
std::array<uint8_t, 2048> mRecvBuffer; // Adjust size as needed std::array<uint8_t, 2048> mRecvBuffer; // Adjust size as needed

View File

@@ -4,6 +4,8 @@
#include <columnlynx/common/net/virtual_interface.hpp> #include <columnlynx/common/net/virtual_interface.hpp>
// This is all fucking voodoo dark magic.
namespace ColumnLynx::Net { namespace ColumnLynx::Net {
// ------------------------------ Constructor ------------------------------ // ------------------------------ Constructor ------------------------------
VirtualInterface::VirtualInterface(const std::string& ifName) VirtualInterface::VirtualInterface(const std::string& ifName)

View File

@@ -196,6 +196,13 @@ namespace ColumnLynx::Net::TCP {
Nonce symNonce{}; // All zeros Nonce symNonce{}; // All zeros
uint32_t clientIP = SessionRegistry::getInstance().getFirstAvailableIP(); uint32_t clientIP = SessionRegistry::getInstance().getFirstAvailableIP();
if (clientIP == 0) {
Utils::warn("Out of available IPs! Disconnecting client " + reqAddr);
disconnect();
return;
}
Protocol::TunConfig tunConfig{}; Protocol::TunConfig tunConfig{};
tunConfig.version = Utils::protocolVersion(); tunConfig.version = Utils::protocolVersion();
tunConfig.prefixLength = 24; tunConfig.prefixLength = 24;