Test Fix panic on disconnect
This commit is contained in:
@@ -186,7 +186,7 @@ namespace ColumnLynx::Utils {
|
|||||||
|
|
||||||
// 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 MASTER THREAD PANIC! \033[0m***\n";
|
||||||
std::cerr << "Reason: " << reason << "\n";
|
std::cerr << "Reason: " << reason << "\n";
|
||||||
std::cerr << "Dumping panic trace...\n";
|
std::cerr << "Dumping panic trace...\n";
|
||||||
|
|
||||||
|
|||||||
@@ -76,5 +76,6 @@ namespace ColumnLynx::Net::TCP {
|
|||||||
std::chrono::steady_clock::time_point mLastHeartbeatReceived;
|
std::chrono::steady_clock::time_point mLastHeartbeatReceived;
|
||||||
std::chrono::steady_clock::time_point mLastHeartbeatSent;
|
std::chrono::steady_clock::time_point mLastHeartbeatSent;
|
||||||
int mMissedHeartbeats = 0;
|
int mMissedHeartbeats = 0;
|
||||||
|
std::string mRemoteIP; // Cached remote IP to avoid calling remote_endpoint() on closed sockets
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -78,6 +78,17 @@ int main(int argc, char** argv) {
|
|||||||
std::shared_ptr<VirtualInterface> tun = std::make_shared<VirtualInterface>(optionsObj["interface"].as<std::string>());
|
std::shared_ptr<VirtualInterface> tun = std::make_shared<VirtualInterface>(optionsObj["interface"].as<std::string>());
|
||||||
log("Using virtual interface: " + tun->getName());
|
log("Using virtual interface: " + tun->getName());
|
||||||
|
|
||||||
|
// Get network configuration from config file
|
||||||
|
std::string networkString = config.find("NETWORK") != config.end() ? config.find("NETWORK")->second : "10.10.0.0";
|
||||||
|
uint8_t subnetMask = config.find("SUBNET_MASK") != config.end() ? std::stoi(config.find("SUBNET_MASK")->second) : 24;
|
||||||
|
uint32_t baseIP = VirtualInterface::stringToIpv4(networkString);
|
||||||
|
uint32_t serverIP = baseIP + 1; // e.g., 10.10.0.1
|
||||||
|
|
||||||
|
// Configure the server's TUN interface with point-to-point mode
|
||||||
|
// Server acts as a peer to clients, so use point-to-point configuration
|
||||||
|
tun->configureIP(serverIP, baseIP, subnetMask, 1420);
|
||||||
|
log("Configured TUN interface with IP " + VirtualInterface::ipv4ToString(serverIP) + " peer " + VirtualInterface::ipv4ToString(baseIP));
|
||||||
|
|
||||||
// Generate a temporary keypair, replace with actual CA signed keys later (Note, these are stored in memory)
|
// Generate a temporary keypair, replace with actual CA signed keys later (Note, these are stored in memory)
|
||||||
std::shared_ptr<LibSodiumWrapper> sodiumWrapper = std::make_shared<LibSodiumWrapper>();
|
std::shared_ptr<LibSodiumWrapper> sodiumWrapper = std::make_shared<LibSodiumWrapper>();
|
||||||
|
|
||||||
@@ -134,7 +145,7 @@ int main(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const uint8_t* ip = packet.data();
|
const uint8_t* ip = packet.data();
|
||||||
uint32_t dstIP = ntohl(*(uint32_t*)(ip + 16)); // IPv4 destination address offset in IPv6-mapped header
|
uint32_t dstIP = ntohl(*(uint32_t*)(ip + 16)); // IPv4 destination address
|
||||||
|
|
||||||
auto session = SessionRegistry::getInstance().getByIP(dstIP);
|
auto session = SessionRegistry::getInstance().getByIP(dstIP);
|
||||||
if (!session) {
|
if (!session) {
|
||||||
|
|||||||
@@ -6,21 +6,28 @@
|
|||||||
|
|
||||||
namespace ColumnLynx::Net::TCP {
|
namespace ColumnLynx::Net::TCP {
|
||||||
void TCPConnection::start() {
|
void TCPConnection::start() {
|
||||||
|
try {
|
||||||
|
// Cache the remote IP early to avoid calling remote_endpoint() on closed sockets later
|
||||||
|
mRemoteIP = mHandler->socket().remote_endpoint().address().to_string();
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
mRemoteIP = "unknown";
|
||||||
|
Utils::warn("Failed to get remote endpoint: " + std::string(e.what()));
|
||||||
|
}
|
||||||
|
|
||||||
mHandler->onMessage([this](AnyMessageType type, const std::string& data) {
|
mHandler->onMessage([this](AnyMessageType type, const std::string& data) {
|
||||||
mHandleMessage(static_cast<ClientMessageType>(MessageHandler::toUint8(type)), data);
|
mHandleMessage(static_cast<ClientMessageType>(MessageHandler::toUint8(type)), data);
|
||||||
});
|
});
|
||||||
|
|
||||||
mHandler->onDisconnect([this](const asio::error_code& ec) {
|
mHandler->onDisconnect([this](const asio::error_code& ec) {
|
||||||
// Peer has closed; finalize locally without sending RST
|
// Peer has closed; finalize locally without sending RST
|
||||||
std::string ip = mHandler->socket().remote_endpoint().address().to_string();
|
Utils::log("Client disconnected: " + mRemoteIP + " - " + ec.message());
|
||||||
Utils::log("Client disconnected: " + ip + " - " + ec.message());
|
|
||||||
asio::error_code ec2;
|
asio::error_code ec2;
|
||||||
mHandler->socket().close(ec2);
|
mHandler->socket().close(ec2);
|
||||||
|
|
||||||
SessionRegistry::getInstance().erase(mConnectionSessionID);
|
SessionRegistry::getInstance().erase(mConnectionSessionID);
|
||||||
SessionRegistry::getInstance().deallocIP(mConnectionSessionID);
|
SessionRegistry::getInstance().deallocIP(mConnectionSessionID);
|
||||||
|
|
||||||
Utils::log("Closed connection to " + ip);
|
Utils::log("Closed connection to " + mRemoteIP);
|
||||||
|
|
||||||
if (mOnDisconnect) {
|
if (mOnDisconnect) {
|
||||||
mOnDisconnect(shared_from_this());
|
mOnDisconnect(shared_from_this());
|
||||||
@@ -31,7 +38,7 @@ namespace ColumnLynx::Net::TCP {
|
|||||||
mStartHeartbeat();
|
mStartHeartbeat();
|
||||||
|
|
||||||
// Placeholder for message handling setup
|
// Placeholder for message handling setup
|
||||||
Utils::log("Client connected: " + mHandler->socket().remote_endpoint().address().to_string());
|
Utils::log("Client connected: " + mRemoteIP);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TCPConnection::sendMessage(ServerMessageType type, const std::string& data) {
|
void TCPConnection::sendMessage(ServerMessageType type, const std::string& data) {
|
||||||
@@ -45,8 +52,6 @@ namespace ColumnLynx::Net::TCP {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TCPConnection::disconnect(bool echo) {
|
void TCPConnection::disconnect(bool echo) {
|
||||||
std::string ip = mHandler->socket().remote_endpoint().address().to_string();
|
|
||||||
|
|
||||||
if (echo) {
|
if (echo) {
|
||||||
mHandler->sendMessage(ServerMessageType::GRACEFUL_DISCONNECT, "Server initiated disconnect.");
|
mHandler->sendMessage(ServerMessageType::GRACEFUL_DISCONNECT, "Server initiated disconnect.");
|
||||||
}
|
}
|
||||||
@@ -58,7 +63,7 @@ namespace ColumnLynx::Net::TCP {
|
|||||||
Utils::error("Error during socket shutdown: " + ec.message());
|
Utils::error("Error during socket shutdown: " + ec.message());
|
||||||
}
|
}
|
||||||
// Do not close immediately; final cleanup happens in onDisconnect
|
// Do not close immediately; final cleanup happens in onDisconnect
|
||||||
Utils::log("Initiated graceful disconnect (half-close) to " + ip);
|
Utils::log("Initiated graceful disconnect (half-close) to " + mRemoteIP);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t TCPConnection::getSessionID() const {
|
uint64_t TCPConnection::getSessionID() const {
|
||||||
@@ -102,7 +107,7 @@ namespace ColumnLynx::Net::TCP {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TCPConnection::mHandleMessage(ClientMessageType type, const std::string& data) {
|
void TCPConnection::mHandleMessage(ClientMessageType type, const std::string& data) {
|
||||||
std::string reqAddr = mHandler->socket().remote_endpoint().address().to_string();
|
std::string& reqAddr = mRemoteIP;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case ClientMessageType::HANDSHAKE_INIT: {
|
case ClientMessageType::HANDSHAKE_INIT: {
|
||||||
|
|||||||
Reference in New Issue
Block a user