Version b0.1 (Beta 0.1) - Refactor some stuff and move session_registry to .cpp file
This commit is contained in:
@@ -6,7 +6,7 @@ cmake_minimum_required(VERSION 3.16)
|
|||||||
# If MAJOR is 0, and MINOR > 0, Version is BETA
|
# If MAJOR is 0, and MINOR > 0, Version is BETA
|
||||||
|
|
||||||
project(ColumnLynx
|
project(ColumnLynx
|
||||||
VERSION 0.0.6
|
VERSION 0.1.0
|
||||||
LANGUAGES CXX
|
LANGUAGES CXX
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,9 @@
|
|||||||
#include <array>
|
#include <array>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <sodium.h>
|
#include <sodium.h>
|
||||||
|
#include <mutex>
|
||||||
|
#include <atomic>
|
||||||
|
#include <asio.hpp>
|
||||||
#include <columnlynx/common/utils.hpp>
|
#include <columnlynx/common/utils.hpp>
|
||||||
#include <columnlynx/common/libsodium_wrapper.hpp>
|
#include <columnlynx/common/libsodium_wrapper.hpp>
|
||||||
|
|
||||||
@@ -49,107 +52,36 @@ namespace ColumnLynx::Net {
|
|||||||
static SessionRegistry& getInstance() { static SessionRegistry instance; return instance; }
|
static SessionRegistry& getInstance() { static SessionRegistry instance; return instance; }
|
||||||
|
|
||||||
// Insert or replace a session entry
|
// 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);
|
|
||||||
mSessions[sessionID] = std::move(state);
|
|
||||||
mIPSessions[mSessions[sessionID]->clientTunIP] = mSessions[sessionID];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lookup a session entry by session ID
|
// 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);
|
|
||||||
auto it = mSessions.find(sessionID);
|
|
||||||
return (it == mSessions.end()) ? nullptr : it->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lookup a session entry by IPv4
|
// 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);
|
|
||||||
auto it = mIPSessions.find(ip);
|
|
||||||
return (it == mIPSessions.end()) ? nullptr : it->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get a snapshot of the Session Registry
|
// 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::shared_lock lock(mMutex);
|
|
||||||
snap = mSessions;
|
|
||||||
return snap;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove a session by ID
|
// Remove a session by ID
|
||||||
void erase(uint64_t sessionID) {
|
void erase(uint64_t sessionID);
|
||||||
std::unique_lock lock(mMutex);
|
|
||||||
mSessions.erase(sessionID);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cleanup expired sessions
|
// Cleanup expired sessions
|
||||||
void cleanupExpired() {
|
void cleanupExpired();
|
||||||
std::unique_lock lock(mMutex);
|
|
||||||
auto now = std::chrono::steady_clock::now();
|
|
||||||
for (auto it = mSessions.begin(); it != mSessions.end(); ) {
|
|
||||||
if (it->second && it->second->expires <= now) {
|
|
||||||
it = mSessions.erase(it);
|
|
||||||
} else {
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto it = mIPSessions.begin(); it != mIPSessions.end(); ) {
|
|
||||||
if (it->second && it->second->expires <= now) {
|
|
||||||
it = mIPSessions.erase(it);
|
|
||||||
} else {
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the number of registered sessions
|
// Get the number of registered sessions
|
||||||
int size() const {
|
int size() const;
|
||||||
std::shared_lock lock(mMutex);
|
|
||||||
return static_cast<int>(mSessions.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
// IP management
|
// IP management
|
||||||
|
|
||||||
// Get the lowest available IPv4 address; Returns 0 if none available
|
// Get the lowest available IPv4 address; Returns 0 if none available
|
||||||
uint32_t getFirstAvailableIP(uint32_t baseIP, uint8_t mask) const {
|
uint32_t getFirstAvailableIP(uint32_t baseIP, uint8_t mask) const;
|
||||||
std::shared_lock lock(mMutex);
|
|
||||||
|
|
||||||
uint32_t hostCount = (1u << (32 - mask));
|
// Lock IP to session ID; Do NOT call before put() - You will segfault!
|
||||||
uint32_t firstHost = 2;
|
void lockIP(uint64_t sessionID, uint32_t ip);
|
||||||
uint32_t lastHost = hostCount - 2;
|
|
||||||
|
|
||||||
for (uint32_t offset = firstHost; offset <= lastHost; offset++) {
|
// Unlock IP from session ID
|
||||||
uint32_t candidateIP = baseIP + offset;
|
void deallocIP(uint64_t sessionID);
|
||||||
if (mIPSessions.find(candidateIP) == mIPSessions.end()) {
|
|
||||||
return candidateIP;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void lockIP(uint64_t sessionID, uint32_t ip) {
|
|
||||||
std::unique_lock lock(mMutex);
|
|
||||||
mSessionIPs[sessionID] = ip;
|
|
||||||
|
|
||||||
/*if (mIPSessions.find(sessionID) == mIPSessions.end()) {
|
|
||||||
Utils::debug("yikes");
|
|
||||||
}*/
|
|
||||||
mIPSessions[ip] = mSessions.find(sessionID)->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
void deallocIP(uint64_t sessionID) {
|
|
||||||
std::unique_lock lock(mMutex);
|
|
||||||
|
|
||||||
auto it = mSessionIPs.find(sessionID);
|
|
||||||
if (it != mSessionIPs.end()) {
|
|
||||||
uint32_t ip = it->second;
|
|
||||||
mIPSessions.erase(ip);
|
|
||||||
mSessionIPs.erase(it);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
mutable std::shared_mutex mMutex;
|
mutable std::shared_mutex mMutex;
|
||||||
|
|||||||
100
src/common/session_registry.cpp
Normal file
100
src/common/session_registry.cpp
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
// session_registry.cpp - Session Registry for ColumnLynx
|
||||||
|
// Copyright (C) 2025 DcruBro
|
||||||
|
// Distributed under the terms of the GNU General Public License, either version 2 only or version 3. See LICENSES/ for details.
|
||||||
|
|
||||||
|
#include <columnlynx/common/net/session_registry.hpp>
|
||||||
|
|
||||||
|
namespace ColumnLynx::Net {
|
||||||
|
void SessionRegistry::put(uint64_t sessionID, std::shared_ptr<SessionState> state) {
|
||||||
|
std::unique_lock lock(mMutex);
|
||||||
|
mSessions[sessionID] = std::move(state);
|
||||||
|
mIPSessions[mSessions[sessionID]->clientTunIP] = mSessions[sessionID];
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<const SessionState> SessionRegistry::get(uint64_t sessionID) const {
|
||||||
|
std::shared_lock lock(mMutex);
|
||||||
|
auto it = mSessions.find(sessionID);
|
||||||
|
return (it == mSessions.end()) ? nullptr : it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<const SessionState> SessionRegistry::getByIP(uint32_t ip) const {
|
||||||
|
std::shared_lock lock(mMutex);
|
||||||
|
auto it = mIPSessions.find(ip);
|
||||||
|
return (it == mIPSessions.end()) ? nullptr : it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unordered_map<uint64_t, std::shared_ptr<SessionState>> SessionRegistry::snapshot() const {
|
||||||
|
std::unordered_map<uint64_t, std::shared_ptr<SessionState>> snap;
|
||||||
|
std::shared_lock lock(mMutex);
|
||||||
|
snap = mSessions;
|
||||||
|
return snap;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SessionRegistry::erase(uint64_t sessionID) {
|
||||||
|
std::unique_lock lock(mMutex);
|
||||||
|
mSessions.erase(sessionID);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SessionRegistry::cleanupExpired() {
|
||||||
|
std::unique_lock lock(mMutex);
|
||||||
|
auto now = std::chrono::steady_clock::now();
|
||||||
|
for (auto it = mSessions.begin(); it != mSessions.end(); ) {
|
||||||
|
if (it->second && it->second->expires <= now) {
|
||||||
|
it = mSessions.erase(it);
|
||||||
|
} else {
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto it = mIPSessions.begin(); it != mIPSessions.end(); ) {
|
||||||
|
if (it->second && it->second->expires <= now) {
|
||||||
|
it = mIPSessions.erase(it);
|
||||||
|
} else {
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int SessionRegistry::size() const {
|
||||||
|
std::shared_lock lock(mMutex);
|
||||||
|
return static_cast<int>(mSessions.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t SessionRegistry::getFirstAvailableIP(uint32_t baseIP, uint8_t mask) const {
|
||||||
|
std::shared_lock lock(mMutex);
|
||||||
|
|
||||||
|
uint32_t hostCount = (1u << (32 - mask));
|
||||||
|
uint32_t firstHost = 2;
|
||||||
|
uint32_t lastHost = hostCount - 2;
|
||||||
|
|
||||||
|
for (uint32_t offset = firstHost; offset <= lastHost; offset++) {
|
||||||
|
uint32_t candidateIP = baseIP + offset;
|
||||||
|
if (mIPSessions.find(candidateIP) == mIPSessions.end()) {
|
||||||
|
return candidateIP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SessionRegistry::lockIP(uint64_t sessionID, uint32_t ip) {
|
||||||
|
std::unique_lock lock(mMutex);
|
||||||
|
mSessionIPs[sessionID] = ip;
|
||||||
|
|
||||||
|
/*if (mIPSessions.find(sessionID) == mIPSessions.end()) {
|
||||||
|
Utils::debug("yikes");
|
||||||
|
}*/
|
||||||
|
mIPSessions[ip] = mSessions.find(sessionID)->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SessionRegistry::deallocIP(uint64_t sessionID) {
|
||||||
|
std::unique_lock lock(mMutex);
|
||||||
|
|
||||||
|
auto it = mSessionIPs.find(sessionID);
|
||||||
|
if (it != mSessionIPs.end()) {
|
||||||
|
uint32_t ip = it->second;
|
||||||
|
mIPSessions.erase(ip);
|
||||||
|
mSessionIPs.erase(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -49,7 +49,7 @@ namespace ColumnLynx::Utils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string getVersion() {
|
std::string getVersion() {
|
||||||
return "a0.6";
|
return "b0.1";
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned short serverPort() {
|
unsigned short serverPort() {
|
||||||
|
|||||||
Reference in New Issue
Block a user