Added IPv6 support, added option to disable IPv6 (IPv4-Only mode)
This commit is contained in:
@@ -21,9 +21,39 @@ namespace ColumnLynx::Net::TCP {
|
|||||||
|
|
||||||
class TCPServer {
|
class TCPServer {
|
||||||
public:
|
public:
|
||||||
TCPServer(asio::io_context& ioContext, uint16_t port, Utils::LibSodiumWrapper* sodiumWrapper, bool* hostRunning)
|
TCPServer(asio::io_context& ioContext,
|
||||||
: mIoContext(ioContext), mAcceptor(ioContext, asio::ip::tcp::endpoint(asio::ip::tcp::v4(), port)), mSodiumWrapper(sodiumWrapper), mHostRunning(hostRunning)
|
uint16_t port,
|
||||||
|
Utils::LibSodiumWrapper* sodiumWrapper,
|
||||||
|
bool* hostRunning, bool ipv4Only = false)
|
||||||
|
: mIoContext(ioContext),
|
||||||
|
mAcceptor(ioContext),
|
||||||
|
mSodiumWrapper(sodiumWrapper),
|
||||||
|
mHostRunning(hostRunning)
|
||||||
{
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
|
||||||
|
if (!ipv4Only) {
|
||||||
|
// Try IPv6 first (dual-stack check)
|
||||||
|
asio::ip::tcp::endpoint endpoint_v6(asio::ip::tcp::v6(), port);
|
||||||
|
mAcceptor.open(endpoint_v6.protocol(), ec);
|
||||||
|
if (!ec) {
|
||||||
|
mAcceptor.set_option(asio::ip::v6_only(false), ec); // Allow dual-stack if possible
|
||||||
|
mAcceptor.bind(endpoint_v6, ec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback to IPv4 if anything failed
|
||||||
|
if (ec || ipv4Only) {
|
||||||
|
Utils::warn("TCP: IPv6 unavailable (" + ec.message() + "), falling back to IPv4 only");
|
||||||
|
|
||||||
|
asio::ip::tcp::endpoint endpoint_v4(asio::ip::tcp::v4(), port);
|
||||||
|
mAcceptor.close(); // ensure clean state
|
||||||
|
mAcceptor.open(endpoint_v4.protocol());
|
||||||
|
mAcceptor.bind(endpoint_v4);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start listening
|
||||||
|
mAcceptor.listen();
|
||||||
Utils::log("Started TCP server on port " + std::to_string(port));
|
Utils::log("Started TCP server on port " + std::to_string(port));
|
||||||
mStartAccept();
|
mStartAccept();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,9 +12,31 @@
|
|||||||
namespace ColumnLynx::Net::UDP {
|
namespace ColumnLynx::Net::UDP {
|
||||||
class UDPServer {
|
class UDPServer {
|
||||||
public:
|
public:
|
||||||
UDPServer(asio::io_context& ioContext, uint16_t port, bool* hostRunning)
|
UDPServer(asio::io_context& ioContext, uint16_t port, bool* hostRunning, bool ipv4Only = false)
|
||||||
: mSocket(ioContext, asio::ip::udp::endpoint(asio::ip::udp::v4(), port)), mHostRunning(hostRunning)
|
: mSocket(ioContext), mHostRunning(hostRunning)
|
||||||
{
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
|
||||||
|
if (!ipv4Only) {
|
||||||
|
// Try IPv6 first (dual-stack check)
|
||||||
|
asio::ip::udp::endpoint endpoint_v6(asio::ip::udp::v6(), port);
|
||||||
|
mSocket.open(endpoint_v6.protocol(), ec);
|
||||||
|
if (!ec) {
|
||||||
|
mSocket.set_option(asio::ip::v6_only(false), ec); // Allow dual-stack if possible
|
||||||
|
mSocket.bind(endpoint_v6, ec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback to IPv4 if anything failed
|
||||||
|
if (ec || ipv4Only) {
|
||||||
|
Utils::warn("UDP: IPv6 unavailable (" + ec.message() + "), falling back to IPv4 only");
|
||||||
|
|
||||||
|
asio::ip::udp::endpoint endpoint_v4(asio::ip::udp::v4(), port);
|
||||||
|
mSocket.close(); // ensure clean state
|
||||||
|
mSocket.open(endpoint_v4.protocol());
|
||||||
|
mSocket.bind(endpoint_v4);
|
||||||
|
}
|
||||||
|
|
||||||
Utils::log("Started UDP server on port " + std::to_string(port));
|
Utils::log("Started UDP server on port " + std::to_string(port));
|
||||||
mStartReceive();
|
mStartReceive();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ int main(int argc, char** argv) {
|
|||||||
("h,help", "Print help")
|
("h,help", "Print help")
|
||||||
("s,server", "Server address", cxxopts::value<std::string>()->default_value("127.0.0.1"))
|
("s,server", "Server address", cxxopts::value<std::string>()->default_value("127.0.0.1"))
|
||||||
("p,port", "Server port", cxxopts::value<uint16_t>()->default_value(std::to_string(serverPort())))
|
("p,port", "Server port", cxxopts::value<uint16_t>()->default_value(std::to_string(serverPort())))
|
||||||
("as,allow-selfsigned", "Allow self-signed certificates", cxxopts::value<bool>()->default_value("false"));
|
("allow-selfsigned", "Allow self-signed certificates", cxxopts::value<bool>()->default_value("false"));
|
||||||
|
|
||||||
bool insecureMode = options.parse(argc, argv).count("allow-selfsigned") > 0;
|
bool insecureMode = options.parse(argc, argv).count("allow-selfsigned") > 0;
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#include <columnlynx/server/net/udp/udp_server.hpp>
|
#include <columnlynx/server/net/udp/udp_server.hpp>
|
||||||
#include <columnlynx/common/libsodium_wrapper.hpp>
|
#include <columnlynx/common/libsodium_wrapper.hpp>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
#include <cxxopts/cxxopts.hpp>
|
||||||
|
|
||||||
using asio::ip::tcp;
|
using asio::ip::tcp;
|
||||||
using namespace ColumnLynx::Utils;
|
using namespace ColumnLynx::Utils;
|
||||||
@@ -33,9 +34,22 @@ int main(int argc, char** argv) {
|
|||||||
sigaction(SIGINT, &action, nullptr);
|
sigaction(SIGINT, &action, nullptr);
|
||||||
sigaction(SIGTERM, &action, nullptr);
|
sigaction(SIGTERM, &action, nullptr);
|
||||||
|
|
||||||
|
cxxopts::Options options("columnlynx_server", "ColumnLynx Server Application");
|
||||||
|
|
||||||
|
options.add_options()
|
||||||
|
("h,help", "Print help")
|
||||||
|
("4,ipv4-only", "Force IPv4 only operation", cxxopts::value<bool>()->default_value("false"));
|
||||||
|
|
||||||
PanicHandler::init();
|
PanicHandler::init();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
auto result = options.parse(argc, argv);
|
||||||
|
if (result.count("help")) {
|
||||||
|
std::cout << options.help() << std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ipv4Only = result["ipv4-only"].as<bool>();
|
||||||
|
|
||||||
log("ColumnLynx Server, Version " + getVersion());
|
log("ColumnLynx Server, Version " + getVersion());
|
||||||
log("This software is licensed under the GPLv2 only OR the GPLv3. See LICENSES/ for details.");
|
log("This software is licensed under the GPLv2 only OR the GPLv3. See LICENSES/ for details.");
|
||||||
@@ -49,8 +63,8 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
asio::io_context io;
|
asio::io_context io;
|
||||||
|
|
||||||
auto server = std::make_shared<TCPServer>(io, serverPort(), &sodiumWrapper, &hostRunning);
|
auto server = std::make_shared<TCPServer>(io, serverPort(), &sodiumWrapper, &hostRunning, ipv4Only);
|
||||||
auto udpServer = std::make_shared<UDPServer>(io, serverPort(), &hostRunning);
|
auto udpServer = std::make_shared<UDPServer>(io, serverPort(), &hostRunning, ipv4Only);
|
||||||
|
|
||||||
asio::signal_set signals(io, SIGINT, SIGTERM);
|
asio::signal_set signals(io, SIGINT, SIGTERM);
|
||||||
signals.async_wait([&](const std::error_code&, int) {
|
signals.async_wait([&](const std::error_code&, int) {
|
||||||
|
|||||||
Reference in New Issue
Block a user