Skip to content

Commit

Permalink
configure: add ipv4 mode
Browse files Browse the repository at this point in the history
This is difficult since libnet and java/net need to agree on whether
preferIPv4Stack is set, or else libnet will create sockets java/net
can't use. Work around this by setting the launcher vmargs, as libnet is
already loaded by the time we get to main().
  • Loading branch information
Adam- committed Jan 21, 2025
1 parent 5d4a3ed commit a4deeb9
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 18 deletions.
24 changes: 24 additions & 0 deletions src/main/java/net/runelite/launcher/ConfigurationFrame.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Nullable;
import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
Expand All @@ -57,6 +59,7 @@ public class ConfigurationFrame extends JFrame
private final JCheckBox chkboxSkipTlsVerification;
private final JCheckBox chkboxNoUpdates;
private final JCheckBox chkboxSafemode;
private final JCheckBox chkboxIpv4;
private final JTextField txtScale;
private final JTextArea txtClientArguments;
private final JTextArea txtJvmArguments;
Expand Down Expand Up @@ -119,6 +122,12 @@ private ConfigurationFrame(LauncherSettings settings)
Boolean.TRUE.equals(settings.safemode)
));

topPanel.add(chkboxIpv4 = checkbox(
"IPv4",
"Prefer IPv4 over IPv6",
Boolean.TRUE.equals(settings.ipv4)
));

pane.add(topPanel);

var midPanel = new JPanel();
Expand Down Expand Up @@ -198,6 +207,7 @@ private void save(ActionEvent l)
settings.skipTlsVerification = chkboxSkipTlsVerification.isSelected();
settings.noupdates = chkboxNoUpdates.isSelected();
settings.safemode = chkboxSafemode.isSelected();
settings.ipv4 = chkboxIpv4.isSelected();

var t = txtScale.getText();
settings.scale = null;
Expand Down Expand Up @@ -227,6 +237,20 @@ private void save(ActionEvent l)

LauncherSettings.saveSettings(settings);

// IPv4 change requires patching packr config
PackrConfig.patch(config ->
{
List<String> vmArgs = (List) config.computeIfAbsent("vmArgs", k -> new ArrayList<>());
if (settings.ipv4)
{
vmArgs.add("-Djava.net.preferIPv4Stack=true");
}
else
{
vmArgs.remove("-Djava.net.preferIPv4Stack=true");
}
});

log.info("Updated launcher configuration:" + System.lineSeparator() + "{}", settings.configurationStr());

dispose();
Expand Down
13 changes: 9 additions & 4 deletions src/main/java/net/runelite/launcher/Launcher.java
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ public static void main(String[] args)

if (postInstall)
{
postInstall();
postInstall(settings);
return;
}

Expand Down Expand Up @@ -343,7 +343,7 @@ public static void main(String[] args)
}

// update packr vmargs to the launcher vmargs from bootstrap.
PackrConfig.updateLauncherArgs(bootstrap);
PackrConfig.updateLauncherArgs(bootstrap, settings);

// Determine artifacts for this OS
List<Artifact> artifacts = Arrays.stream(bootstrap.getArtifacts())
Expand Down Expand Up @@ -593,6 +593,11 @@ private static List<String> getJvmArgs(LauncherSettings settings)
{
var args = new ArrayList<>(settings.jvmArguments);

if (settings.ipv4)
{
args.add("-Djava.net.preferIPv4Stack=true");
}

var envArgs = System.getenv("RUNELITE_VMARGS");
if (!Strings.isNullOrEmpty(envArgs))
{
Expand Down Expand Up @@ -921,7 +926,7 @@ static boolean isJava17()
return Runtime.version().feature() >= 16;
}

private static void postInstall()
private static void postInstall(LauncherSettings settings)
{
Bootstrap bootstrap;
try
Expand All @@ -934,7 +939,7 @@ private static void postInstall()
return;
}

PackrConfig.updateLauncherArgs(bootstrap);
PackrConfig.updateLauncherArgs(bootstrap, settings);

log.info("Performed postinstall steps");
}
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/net/runelite/launcher/LauncherSettings.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ class LauncherSettings
boolean skipTlsVerification;
boolean noupdates;
boolean safemode;
boolean ipv4;
@Nullable
Double scale;
List<String> clientArguments = Collections.emptyList();
Expand Down Expand Up @@ -141,6 +142,7 @@ String configurationStr()
" skip tls verification: {}" + System.lineSeparator() +
" noupdates: {}" + System.lineSeparator() +
" safe mode: {}" + System.lineSeparator() +
" ipv4: {}" + System.lineSeparator() +
" scale: {}" + System.lineSeparator() +
" client arguments: {}" + System.lineSeparator() +
" jvm arguments: {}" + System.lineSeparator() +
Expand All @@ -152,6 +154,7 @@ String configurationStr()
skipTlsVerification,
noupdates,
safemode,
ipv4,
scale == null ? "system" : scale,
clientArguments.isEmpty() ? "none" : clientArguments,
jvmArguments.isEmpty() ? "none" : jvmArguments,
Expand Down
54 changes: 40 additions & 14 deletions src/main/java/net/runelite/launcher/PackrConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,47 @@
import java.nio.file.AtomicMoveNotSupportedException;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import lombok.extern.slf4j.Slf4j;
import net.runelite.launcher.beans.Bootstrap;

@Slf4j
class PackrConfig
{
// Update the packr config
static void updateLauncherArgs(Bootstrap bootstrap)
static void updateLauncherArgs(Bootstrap bootstrap, LauncherSettings settings)
{
String[] bootstrapVmArgs = getVmArgs(bootstrap);
if (bootstrapVmArgs == null || bootstrapVmArgs.length == 0)
{
log.warn("Launcher args are empty");
return;
}

List<String> vmArgs = new ArrayList<>(Arrays.asList(bootstrapVmArgs));

// java.net.preferIPv4Stack needs to be set prior to libnet *loading* (it is read in net_util.c JNI_OnLoad).
// Failure to keep preferIPv4Stack consistent between libnet and java/net results in disagreements over
// which socket types can be used.
if (settings.ipv4)
{
vmArgs.add("-Djava.net.preferIPv4Stack=true");
}

Map<String, String> env = getEnv(bootstrap);

patch(config ->
{
config.put("vmArgs", vmArgs);
config.put("env", env);
});
}

static void patch(Consumer<Map> configConsumer)
{
var os = OS.getOs();
if (os != OS.OSType.Windows && os != OS.OSType.MacOS)
Expand All @@ -71,27 +103,19 @@ static void updateLauncherArgs(Bootstrap bootstrap)
}
catch (IOException | JsonIOException | JsonSyntaxException e)
{
log.warn("error deserializing packr vm args!", e);
log.warn("error deserializing launcher vm args!", e);
return;
}

if (config == null)
{
// this can't happen when run from the launcher, because an invalid packr config would prevent the launcher itself
// from starting. But could happen if the jar launcher was run separately.
log.warn("packr config is null!");
return;
}

String[] argsArr = getArgs(bootstrap);
if (argsArr == null || argsArr.length == 0)
{
log.warn("Launcher args are empty");
log.warn("launcher config is null!");
return;
}

config.put("vmArgs", argsArr);
config.put("env", getEnv(bootstrap));
configConsumer.accept(config);

try
{
Expand All @@ -117,14 +141,16 @@ static void updateLauncherArgs(Bootstrap bootstrap)
log.debug("atomic move not supported", ex);
Files.move(tmpFile.toPath(), configFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
}

log.debug("patched packr config");
}
catch (IOException e)
{
log.warn("error updating packr vm args!", e);
log.warn("error updating launcher vm args!", e);
}
}

private static String[] getArgs(Bootstrap bootstrap)
private static String[] getVmArgs(Bootstrap bootstrap)
{
return Launcher.isJava17() ? getArgsJvm17(bootstrap) : getArgsJvm11(bootstrap);
}
Expand Down

0 comments on commit a4deeb9

Please sign in to comment.