diff --git a/include/columnlynx/common/panic_handler.hpp b/include/columnlynx/common/panic_handler.hpp index 8e9867c..044fdde 100644 --- a/include/columnlynx/common/panic_handler.hpp +++ b/include/columnlynx/common/panic_handler.hpp @@ -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. 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 << "Dumping panic trace...\n"; diff --git a/include/columnlynx/server/net/tcp/tcp_connection.hpp b/include/columnlynx/server/net/tcp/tcp_connection.hpp index 212a470..3a45b7b 100644 --- a/include/columnlynx/server/net/tcp/tcp_connection.hpp +++ b/include/columnlynx/server/net/tcp/tcp_connection.hpp @@ -76,5 +76,6 @@ namespace ColumnLynx::Net::TCP { std::chrono::steady_clock::time_point mLastHeartbeatReceived; std::chrono::steady_clock::time_point mLastHeartbeatSent; int mMissedHeartbeats = 0; + std::string mRemoteIP; // Cached remote IP to avoid calling remote_endpoint() on closed sockets }; } \ No newline at end of file diff --git a/src/server/main.cpp b/src/server/main.cpp index 080018b..948df83 100644 --- a/src/server/main.cpp +++ b/src/server/main.cpp @@ -78,6 +78,17 @@ int main(int argc, char** argv) { std::shared_ptr tun = std::make_shared(optionsObj["interface"].as()); 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) std::shared_ptr sodiumWrapper = std::make_shared(); @@ -134,7 +145,7 @@ int main(int argc, char** argv) { } 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); if (!session) { diff --git a/src/server/net/tcp/tcp_connection.cpp b/src/server/net/tcp/tcp_connection.cpp index 6eaca97..ffbfbb7 100644 --- a/src/server/net/tcp/tcp_connection.cpp +++ b/src/server/net/tcp/tcp_connection.cpp @@ -6,21 +6,28 @@ namespace ColumnLynx::Net::TCP { 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) { mHandleMessage(static_cast(MessageHandler::toUint8(type)), data); }); mHandler->onDisconnect([this](const asio::error_code& ec) { // Peer has closed; finalize locally without sending RST - std::string ip = mHandler->socket().remote_endpoint().address().to_string(); - Utils::log("Client disconnected: " + ip + " - " + ec.message()); + Utils::log("Client disconnected: " + mRemoteIP + " - " + ec.message()); asio::error_code ec2; mHandler->socket().close(ec2); SessionRegistry::getInstance().erase(mConnectionSessionID); SessionRegistry::getInstance().deallocIP(mConnectionSessionID); - Utils::log("Closed connection to " + ip); + Utils::log("Closed connection to " + mRemoteIP); if (mOnDisconnect) { mOnDisconnect(shared_from_this()); @@ -31,7 +38,7 @@ namespace ColumnLynx::Net::TCP { mStartHeartbeat(); // 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) { @@ -45,8 +52,6 @@ namespace ColumnLynx::Net::TCP { } void TCPConnection::disconnect(bool echo) { - std::string ip = mHandler->socket().remote_endpoint().address().to_string(); - if (echo) { mHandler->sendMessage(ServerMessageType::GRACEFUL_DISCONNECT, "Server initiated disconnect."); } @@ -58,7 +63,7 @@ namespace ColumnLynx::Net::TCP { Utils::error("Error during socket shutdown: " + ec.message()); } // 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 { @@ -102,7 +107,7 @@ namespace ColumnLynx::Net::TCP { } 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) { case ClientMessageType::HANDSHAKE_INIT: {