From c2225ab1da58cf8eb3ac3aab1aab73f2d7a696fa Mon Sep 17 00:00:00 2001 From: Paint_Ninja Date: Fri, 1 Jul 2022 23:38:53 +0100 Subject: [PATCH] Implement full support for IPv6 (#8742) --- build.gradle | 8 +- .../server/LanServerDetection.java.patch | 32 +++++++ .../client/server/LanServerPinger.java.patch | 20 +++++ .../minecraft/network/Connection.java.patch | 2 +- .../ServerConnectionListener.java.patch | 5 +- server_files/args.txt | 1 + .../client/IFluidTypeRenderProperties.java | 5 ++ .../minecraftforge/common/ForgeConfig.java | 7 ++ .../minecraftforge/common/SoundAction.java | 5 ++ .../minecraftforge/common/SoundActions.java | 5 ++ .../common/extensions/IForgeBoat.java | 5 ++ .../common/extensions/IForgeLivingEntity.java | 5 ++ .../fluids/FluidInteractionRegistry.java | 5 ++ .../net/minecraftforge/fluids/FluidType.java | 5 ++ .../network/DualStackUtils.java | 88 +++++++++++++++++++ .../debug/fluid/FluidTypeTest.java | 5 ++ 16 files changed, 198 insertions(+), 5 deletions(-) create mode 100644 patches/minecraft/net/minecraft/client/server/LanServerDetection.java.patch create mode 100644 patches/minecraft/net/minecraft/client/server/LanServerPinger.java.patch create mode 100644 src/main/java/net/minecraftforge/network/DualStackUtils.java diff --git a/build.gradle b/build.gradle index 699dd4002db..8e449bd891b 100644 --- a/build.gradle +++ b/build.gradle @@ -431,6 +431,8 @@ def sharedFmlonlyForge = { Project prj -> run.args '--fml.forgeGroup', prj.group run.args '--fml.mcpVersion', MCP_VERSION + run.jvmArgs '-Djava.net.preferIPv6Addresses=system' + if (run.name.contains('client')) { run.client true } else { @@ -634,7 +636,8 @@ project(':fmlonly') { '--fml.mcVersion', MC_VERSION, '--fml.forgeGroup', project.group, '--fml.mcpVersion', MCP_VERSION], - jvm: ["-DignoreList=${fmlonly_client.properties.ignoreList},\${version_name}.jar", + jvm: ['-Djava.net.preferIPv6Addresses=system', + "-DignoreList=${fmlonly_client.properties.ignoreList},\${version_name}.jar", "-DmergeModules=${fmlonly_client.properties.mergeModules}", '-DlibraryDirectory=${library_directory}', '-p', Util.getArtifacts(project, configurations.moduleonly, false).values().collect{"\${library_directory}/${it.downloads.artifact.path}"}.join('${classpath_separator}'), @@ -1264,7 +1267,8 @@ project(':forge') { '--fml.mcVersion', MC_VERSION, '--fml.forgeGroup', project.group, '--fml.mcpVersion', MCP_VERSION], - jvm: ["-DignoreList=${forge_client.properties.ignoreList},\${version_name}.jar", + jvm: ['-Djava.net.preferIPv6Addresses=system', + "-DignoreList=${forge_client.properties.ignoreList},\${version_name}.jar", "-DmergeModules=${forge_client.properties.mergeModules}", '-DlibraryDirectory=${library_directory}', '-p', Util.getArtifacts(project, configurations.moduleonly, false).values().collect{'${library_directory}/' + it.downloads.artifact.path}.join('${classpath_separator}'), diff --git a/patches/minecraft/net/minecraft/client/server/LanServerDetection.java.patch b/patches/minecraft/net/minecraft/client/server/LanServerDetection.java.patch new file mode 100644 index 00000000000..6d07e0ad486 --- /dev/null +++ b/patches/minecraft/net/minecraft/client/server/LanServerDetection.java.patch @@ -0,0 +1,32 @@ +--- a/net/minecraft/client/server/LanServerDetection.java ++++ b/net/minecraft/client/server/LanServerDetection.java +@@ -33,7 +_,7 @@ + this.setDaemon(true); + this.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(LanServerDetection.f_120082_)); + this.f_120088_ = new MulticastSocket(4445); +- this.f_120087_ = InetAddress.getByName("224.0.2.60"); ++ this.f_120087_ = InetAddress.getByName(LanServerPinger.f_174974_); + this.f_120088_.setSoTimeout(5000); + this.f_120088_.joinGroup(this.f_120087_); + } +@@ -88,7 +_,19 @@ + String s = LanServerPinger.m_120111_(p_120097_); + String s1 = LanServerPinger.m_120116_(p_120097_); + if (s1 != null) { +- s1 = p_120098_.getHostAddress() + ":" + s1; ++ if (net.minecraftforge.network.DualStackUtils.checkIPv6(p_120098_)) { ++ final String ip; ++ ++ // compress to short form if enabled in config ++ if (net.minecraftforge.common.ForgeConfig.CLIENT.compressLanIPv6Addresses.get()) ++ ip = com.google.common.net.InetAddresses.toAddrString(p_120098_); ++ else ++ ip = p_120098_.getHostAddress(); ++ ++ s1 = "[" + ip + "]:" + s1; ++ } else { ++ s1 = p_120098_.getHostAddress() + ":" + s1; ++ } + boolean flag = false; + + for(LanServer lanserver : this.f_120092_) { diff --git a/patches/minecraft/net/minecraft/client/server/LanServerPinger.java.patch b/patches/minecraft/net/minecraft/client/server/LanServerPinger.java.patch new file mode 100644 index 00000000000..e89de405628 --- /dev/null +++ b/patches/minecraft/net/minecraft/client/server/LanServerPinger.java.patch @@ -0,0 +1,20 @@ +--- a/net/minecraft/client/server/LanServerPinger.java ++++ b/net/minecraft/client/server/LanServerPinger.java +@@ -16,7 +_,7 @@ + public class LanServerPinger extends Thread { + private static final AtomicInteger f_120101_ = new AtomicInteger(0); + private static final Logger f_120102_ = LogUtils.getLogger(); +- public static final String f_174974_ = "224.0.2.60"; ++ public static final String f_174974_ = net.minecraftforge.network.DualStackUtils.getMulticastGroup(); + public static final int f_174975_ = 4445; + private static final long f_174976_ = 1500L; + private final String f_120103_; +@@ -39,7 +_,7 @@ + + while(!this.isInterrupted() && this.f_120105_) { + try { +- InetAddress inetaddress = InetAddress.getByName("224.0.2.60"); ++ InetAddress inetaddress = InetAddress.getByName(f_174974_); + DatagramPacket datagrampacket = new DatagramPacket(abyte, abyte.length, inetaddress, 4445); + this.f_120104_.send(datagrampacket); + } catch (IOException ioexception) { diff --git a/patches/minecraft/net/minecraft/network/Connection.java.patch b/patches/minecraft/net/minecraft/network/Connection.java.patch index ddd48339dc2..8b0709eb92e 100644 --- a/patches/minecraft/net/minecraft/network/Connection.java.patch +++ b/patches/minecraft/net/minecraft/network/Connection.java.patch @@ -29,7 +29,7 @@ } public static Connection m_178300_(InetSocketAddress p_178301_, boolean p_178302_) { -+ if (p_178301_.getAddress() instanceof java.net.Inet6Address) System.setProperty("java.net.preferIPv4Stack", "false"); ++ net.minecraftforge.network.DualStackUtils.checkIPv6(p_178301_.getAddress()); final Connection connection = new Connection(PacketFlow.CLIENTBOUND); + connection.activationHandler = net.minecraftforge.network.NetworkHooks::registerClientLoginChannel; Class oclass; diff --git a/patches/minecraft/net/minecraft/server/network/ServerConnectionListener.java.patch b/patches/minecraft/net/minecraft/server/network/ServerConnectionListener.java.patch index 8ae77d96504..a789f7b0570 100644 --- a/patches/minecraft/net/minecraft/server/network/ServerConnectionListener.java.patch +++ b/patches/minecraft/net/minecraft/server/network/ServerConnectionListener.java.patch @@ -15,11 +15,12 @@ }); final MinecraftServer f_9702_; public volatile boolean f_9700_; -@@ -66,6 +_,7 @@ +@@ -66,6 +_,8 @@ } public void m_9711_(@Nullable InetAddress p_9712_, int p_9713_) throws IOException { -+ if (p_9712_ instanceof java.net.Inet6Address) System.setProperty("java.net.preferIPv4Stack", "false"); ++ if (p_9712_ == null) p_9712_ = new java.net.InetSocketAddress(p_9713_).getAddress(); ++ net.minecraftforge.network.DualStackUtils.checkIPv6(p_9712_); synchronized(this.f_9703_) { Class oclass; LazyLoadedValue lazyloadedvalue; diff --git a/server_files/args.txt b/server_files/args.txt index 17252fa80f3..6dd9824f337 100644 --- a/server_files/args.txt +++ b/server_files/args.txt @@ -3,6 +3,7 @@ --add-opens java.base/java.util.jar=cpw.mods.securejarhandler --add-exports java.base/sun.security.util=cpw.mods.securejarhandler --add-exports jdk.naming.dns/com.sun.jndi.dns=java.naming +-Djava.net.preferIPv6Addresses=system -DignoreList=@IGNORE_LIST@ -DlibraryDirectory=libraries -DlegacyClassPath=@CLASS_PATH@ diff --git a/src/main/java/net/minecraftforge/client/IFluidTypeRenderProperties.java b/src/main/java/net/minecraftforge/client/IFluidTypeRenderProperties.java index 2f1f7994cf3..061561232c6 100644 --- a/src/main/java/net/minecraftforge/client/IFluidTypeRenderProperties.java +++ b/src/main/java/net/minecraftforge/client/IFluidTypeRenderProperties.java @@ -1,3 +1,8 @@ +/* + * Copyright (c) Forge Development LLC and contributors + * SPDX-License-Identifier: LGPL-2.1-only + */ + package net.minecraftforge.client; import com.mojang.blaze3d.shaders.FogShape; diff --git a/src/main/java/net/minecraftforge/common/ForgeConfig.java b/src/main/java/net/minecraftforge/common/ForgeConfig.java index 25f3e62a562..80af297e7f0 100644 --- a/src/main/java/net/minecraftforge/common/ForgeConfig.java +++ b/src/main/java/net/minecraftforge/common/ForgeConfig.java @@ -103,6 +103,8 @@ public static class Client { public final BooleanValue useCombinedDepthStencilAttachment; + public final BooleanValue compressLanIPv6Addresses; + Client(ForgeConfigSpec.Builder builder) { builder.comment("Client only settings, mostly things related to rendering") .push("client"); @@ -129,6 +131,11 @@ public static class Client { .translation("forge.configgui.useCombinedDepthStencilAttachment") .define("useCombinedDepthStencilAttachment", false); + compressLanIPv6Addresses = builder + .comment("When enabled, Forge will convert discovered 'Open to LAN' IPv6 addresses to their more compact, compressed representation") + .translation("forge.configgui.compressLanIPv6Addresses") + .define("compressLanIPv6Addresses", true); + builder.pop(); } } diff --git a/src/main/java/net/minecraftforge/common/SoundAction.java b/src/main/java/net/minecraftforge/common/SoundAction.java index e6c25b60b83..bec245d275c 100644 --- a/src/main/java/net/minecraftforge/common/SoundAction.java +++ b/src/main/java/net/minecraftforge/common/SoundAction.java @@ -1,3 +1,8 @@ +/* + * Copyright (c) Forge Development LLC and contributors + * SPDX-License-Identifier: LGPL-2.1-only + */ + package net.minecraftforge.common; import java.util.Map; diff --git a/src/main/java/net/minecraftforge/common/SoundActions.java b/src/main/java/net/minecraftforge/common/SoundActions.java index b7d9b476228..11a752ff590 100644 --- a/src/main/java/net/minecraftforge/common/SoundActions.java +++ b/src/main/java/net/minecraftforge/common/SoundActions.java @@ -1,3 +1,8 @@ +/* + * Copyright (c) Forge Development LLC and contributors + * SPDX-License-Identifier: LGPL-2.1-only + */ + package net.minecraftforge.common; /** diff --git a/src/main/java/net/minecraftforge/common/extensions/IForgeBoat.java b/src/main/java/net/minecraftforge/common/extensions/IForgeBoat.java index 87b144a4757..7399873a38a 100644 --- a/src/main/java/net/minecraftforge/common/extensions/IForgeBoat.java +++ b/src/main/java/net/minecraftforge/common/extensions/IForgeBoat.java @@ -1,3 +1,8 @@ +/* + * Copyright (c) Forge Development LLC and contributors + * SPDX-License-Identifier: LGPL-2.1-only + */ + package net.minecraftforge.common.extensions; import net.minecraft.world.entity.vehicle.Boat; diff --git a/src/main/java/net/minecraftforge/common/extensions/IForgeLivingEntity.java b/src/main/java/net/minecraftforge/common/extensions/IForgeLivingEntity.java index 3120bd96b6a..fc36caa8a77 100644 --- a/src/main/java/net/minecraftforge/common/extensions/IForgeLivingEntity.java +++ b/src/main/java/net/minecraftforge/common/extensions/IForgeLivingEntity.java @@ -1,3 +1,8 @@ +/* + * Copyright (c) Forge Development LLC and contributors + * SPDX-License-Identifier: LGPL-2.1-only + */ + package net.minecraftforge.common.extensions; import net.minecraft.world.entity.LivingEntity; diff --git a/src/main/java/net/minecraftforge/fluids/FluidInteractionRegistry.java b/src/main/java/net/minecraftforge/fluids/FluidInteractionRegistry.java index 8df199e8ca0..ed23c0ce8c1 100644 --- a/src/main/java/net/minecraftforge/fluids/FluidInteractionRegistry.java +++ b/src/main/java/net/minecraftforge/fluids/FluidInteractionRegistry.java @@ -1,3 +1,8 @@ +/* + * Copyright (c) Forge Development LLC and contributors + * SPDX-License-Identifier: LGPL-2.1-only + */ + package net.minecraftforge.fluids; import net.minecraft.core.BlockPos; diff --git a/src/main/java/net/minecraftforge/fluids/FluidType.java b/src/main/java/net/minecraftforge/fluids/FluidType.java index 577b0113671..16d9de42e12 100644 --- a/src/main/java/net/minecraftforge/fluids/FluidType.java +++ b/src/main/java/net/minecraftforge/fluids/FluidType.java @@ -1,3 +1,8 @@ +/* + * Copyright (c) Forge Development LLC and contributors + * SPDX-License-Identifier: LGPL-2.1-only + */ + package net.minecraftforge.fluids; import com.google.common.collect.ImmutableMap; diff --git a/src/main/java/net/minecraftforge/network/DualStackUtils.java b/src/main/java/net/minecraftforge/network/DualStackUtils.java new file mode 100644 index 00000000000..bec3e72a623 --- /dev/null +++ b/src/main/java/net/minecraftforge/network/DualStackUtils.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) Forge Development LLC and contributors + * SPDX-License-Identifier: LGPL-2.1-only + */ + +package net.minecraftforge.network; + +import net.minecraft.client.multiplayer.resolver.ResolvedServerAddress; +import net.minecraft.client.multiplayer.resolver.ServerAddress; +import net.minecraft.client.multiplayer.resolver.ServerNameResolver; +import net.minecraft.util.HttpUtil; + +import javax.annotation.Nullable; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.UnknownHostException; +import java.util.Optional; + +public class DualStackUtils +{ + /** + * Resolve the address and see if Java and the OS return an IPv6 or IPv4 one, then let Netty know + * accordingly (it doesn't understand the {@code java.net.preferIPv6Addresses=system} property). + * + * @param hostAddress The address you want to check + * @return true if IPv6, false if IPv4 + */ + public static boolean checkIPv6(final String hostAddress) + { + final Optional hostAddr = + ServerNameResolver.DEFAULT + .resolveAddress(ServerAddress.parseString(hostAddress)) + .map(ResolvedServerAddress::asInetSocketAddress); + + if (hostAddr.isPresent()) return checkIPv6(hostAddr.get().getAddress()); + else return false; + } + + /** + * Checks if an address is an IPv6 one or an IPv4 one, lets Netty know accordingly and returns the result. + * + * @param inetAddress The address you want to check + * @return true if IPv6, false if IPv4 + */ + public static boolean checkIPv6(final InetAddress inetAddress) + { + if (inetAddress instanceof Inet6Address) + { + System.setProperty("java.net.preferIPv4Stack", "false"); + System.setProperty("java.net.preferIPv6Addresses", "true"); + return true; + } + else + { + System.setProperty("java.net.preferIPv4Stack", "true"); + System.setProperty("java.net.preferIPv6Addresses", "false"); + return false; + } + } + + /** + * Get the device's local IP address, taking into account scenarios where the client's network adapter + * supports IPv6 and has it enabled but the router's LAN does not. + * + * @return the client's local IP address or {@code null} if unable to determine it + */ + @Nullable + public static InetAddress getLocalAddress() + { + final InetAddress localAddr = new InetSocketAddress(HttpUtil.getAvailablePort()).getAddress(); + if (localAddr.isAnyLocalAddress()) return localAddr; + + try + { + return InetAddress.getByName("localhost"); + } + catch (final UnknownHostException e) + { + return null; + } + } + + public static String getMulticastGroup() { + if (checkIPv6(getLocalAddress())) return "FF75:230::60"; + else return "224.0.2.60"; + } +} diff --git a/src/test/java/net/minecraftforge/debug/fluid/FluidTypeTest.java b/src/test/java/net/minecraftforge/debug/fluid/FluidTypeTest.java index aa02fe9cf2a..105459ba14f 100644 --- a/src/test/java/net/minecraftforge/debug/fluid/FluidTypeTest.java +++ b/src/test/java/net/minecraftforge/debug/fluid/FluidTypeTest.java @@ -1,3 +1,8 @@ +/* + * Copyright (c) Forge Development LLC and contributors + * SPDX-License-Identifier: LGPL-2.1-only + */ + package net.minecraftforge.debug.fluid; import com.mojang.blaze3d.shaders.FogShape;