Try to properly check if so_reuseport is available

This commit is contained in:
onebeastchris 2024-04-17 18:16:15 +02:00
parent a24f684123
commit b7bf24b4cf
2 changed files with 21 additions and 5 deletions

View File

@ -49,6 +49,7 @@ public final class Bootstraps {
String kernelVersion; String kernelVersion;
try { try {
kernelVersion = Native.KERNEL_VERSION; kernelVersion = Native.KERNEL_VERSION;
GeyserImpl.getInstance().getLogger().debug("Kernel version: " + kernelVersion);
} catch (Throwable e) { } catch (Throwable e) {
GeyserImpl.getInstance().getLogger().debug("Could not determine kernel version! " + e.getMessage()); GeyserImpl.getInstance().getLogger().debug("Could not determine kernel version! " + e.getMessage());
kernelVersion = null; kernelVersion = null;
@ -67,10 +68,22 @@ public final class Bootstraps {
} }
@SuppressWarnings({"rawtypes, unchecked"}) @SuppressWarnings({"rawtypes, unchecked"})
public static void setupBootstrap(AbstractBootstrap bootstrap) { public static boolean setupBootstrap(AbstractBootstrap bootstrap) {
boolean success = true;
if (REUSEPORT_AVAILABLE) { if (REUSEPORT_AVAILABLE) {
bootstrap.option(UnixChannelOption.SO_REUSEPORT, true); // Guessing whether so_reuseport is available based on kernel version is cool, but unreliable.
Channel channel = bootstrap.register().channel();
if (channel.config().setOption(UnixChannelOption.SO_REUSEPORT, true)) {
bootstrap.option(UnixChannelOption.SO_REUSEPORT, true);
} else {
// If this occurs, we guessed wrong and reuseport is not available
GeyserImpl.getInstance().getLogger().debug("so_reuseport is not available despite version being " + Native.KERNEL_VERSION);
success = false;
}
// Now yeet that channel
channel.close();
} }
return success;
} }
private static int[] fromString(String input) { private static int[] fromString(String input) {

View File

@ -107,7 +107,7 @@ public final class GeyserServer {
@Getter @Getter
private final ExpiringMap<InetSocketAddress, InetSocketAddress> proxiedAddresses; private final ExpiringMap<InetSocketAddress, InetSocketAddress> proxiedAddresses;
private final int listenCount; private int listenCount;
private ChannelFuture[] bootstrapFutures; private ChannelFuture[] bootstrapFutures;
@ -124,8 +124,11 @@ public final class GeyserServer {
this.childGroup = TRANSPORT.eventLoopGroupFactory().apply(threadCount); this.childGroup = TRANSPORT.eventLoopGroupFactory().apply(threadCount);
this.bootstrap = this.createBootstrap(); this.bootstrap = this.createBootstrap();
// setup SO_REUSEPORT if exists // setup SO_REUSEPORT if exists - or, if the option does not actually exist, reset listen count
Bootstraps.setupBootstrap(this.bootstrap); // otherwise, we try to bind multiple times which wont work if so_reuseport is not valid
if (!Bootstraps.setupBootstrap(this.bootstrap)) {
this.listenCount = 1;
}
if (this.geyser.getConfig().getBedrock().isEnableProxyProtocol()) { if (this.geyser.getConfig().getBedrock().isEnableProxyProtocol()) {
this.proxiedAddresses = ExpiringMap.builder() this.proxiedAddresses = ExpiringMap.builder()