Test: proper ipv6 support, still sending v4 to client tun
This commit is contained in:
@@ -34,24 +34,33 @@ namespace ColumnLynx::Net::TCP {
|
||||
// Preload the config map
|
||||
mRawServerConfig = Utils::getConfigMap("server_config", {"NETWORK", "SUBNET_MASK"});
|
||||
|
||||
asio::error_code ec;
|
||||
|
||||
asio::error_code ec_open, ec_v6only, ec_bind;
|
||||
|
||||
if (!ipv4Only) {
|
||||
// Try IPv6 first (dual-stack check)
|
||||
// Try IPv6 (dual-stack if supported)
|
||||
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);
|
||||
|
||||
mAcceptor.open(endpoint_v6.protocol(), ec_open);
|
||||
|
||||
if (!ec_open) {
|
||||
// Try enabling dual-stack, but DO NOT treat failure as fatal
|
||||
mAcceptor.set_option(asio::ip::v6_only(false), ec_v6only);
|
||||
|
||||
// Try binding IPv6
|
||||
mAcceptor.bind(endpoint_v6, ec_bind);
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback to IPv4 if anything failed
|
||||
if (ec || ipv4Only) {
|
||||
Utils::warn("TCP: IPv6 unavailable (" + ec.message() + "), falling back to IPv4 only");
|
||||
|
||||
// If IPv6 bind failed OR IPv6 open failed OR forced IPv4-only
|
||||
if (ipv4Only || ec_open || ec_bind) {
|
||||
if (!ipv4Only)
|
||||
Utils::warn("TCP: IPv6 unavailable (open=" + ec_open.message() +
|
||||
", bind=" + ec_bind.message() +
|
||||
"), falling back to IPv4 only");
|
||||
|
||||
asio::ip::tcp::endpoint endpoint_v4(asio::ip::tcp::v4(), port);
|
||||
mAcceptor.close(); // ensure clean state
|
||||
|
||||
mAcceptor.close(); // guarantee clean state
|
||||
mAcceptor.open(endpoint_v4.protocol());
|
||||
mAcceptor.bind(endpoint_v4);
|
||||
}
|
||||
|
||||
@@ -16,24 +16,37 @@ namespace ColumnLynx::Net::UDP {
|
||||
UDPServer(asio::io_context& ioContext, uint16_t port, std::shared_ptr<bool> hostRunning, bool ipv4Only = false, std::shared_ptr<VirtualInterface> tun = nullptr)
|
||||
: mSocket(ioContext), mHostRunning(hostRunning), mTun(tun)
|
||||
{
|
||||
asio::error_code ec;
|
||||
asio::error_code ec_open, ec_v6only, ec_bind;
|
||||
|
||||
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);
|
||||
|
||||
// Try opening IPv6 socket
|
||||
mSocket.open(endpoint_v6.protocol(), ec_open);
|
||||
|
||||
if (!ec_open) {
|
||||
// Try enabling dual-stack (non fatal if it fails)
|
||||
mSocket.set_option(asio::ip::v6_only(false), ec_v6only);
|
||||
|
||||
// Attempt bind
|
||||
mSocket.bind(endpoint_v6, ec_bind);
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback to IPv4 if anything failed
|
||||
if (ec || ipv4Only) {
|
||||
Utils::warn("UDP: IPv6 unavailable (" + ec.message() + "), falling back to IPv4 only");
|
||||
|
||||
// Fallback to IPv4 if IPv6 is unusable
|
||||
if (ipv4Only || ec_open || ec_bind) {
|
||||
if (!ipv4Only) {
|
||||
Utils::warn(
|
||||
"UDP: IPv6 unavailable (open=" + ec_open.message() +
|
||||
", bind=" + ec_bind.message() +
|
||||
"), falling back to IPv4 only"
|
||||
);
|
||||
}
|
||||
|
||||
asio::ip::udp::endpoint endpoint_v4(asio::ip::udp::v4(), port);
|
||||
mSocket.close(); // ensure clean state
|
||||
|
||||
mSocket.close();
|
||||
mSocket = asio::ip::udp::socket(ioContext); // fully reset internal state
|
||||
mSocket.open(endpoint_v4.protocol());
|
||||
mSocket.bind(endpoint_v4);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user