diff --git a/api/src/main/java/com/velocitypowered/api/proxy/config/ProxyConfig.java b/api/src/main/java/com/velocitypowered/api/proxy/config/ProxyConfig.java index 3efa22c78..da3a44208 100644 --- a/api/src/main/java/com/velocitypowered/api/proxy/config/ProxyConfig.java +++ b/api/src/main/java/com/velocitypowered/api/proxy/config/ProxyConfig.java @@ -150,4 +150,11 @@ public interface ProxyConfig { * @return read timeout (in milliseconds) */ int getReadTimeout(); + + /** + * Get how long this proxy will wait until performing an initial read timeout. + * + * @return read timeout (in milliseconds) + */ + int getInitialReadTimeout(); } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/config/VelocityConfiguration.java b/proxy/src/main/java/com/velocitypowered/proxy/config/VelocityConfiguration.java index 904d469b3..6420f0a42 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/config/VelocityConfiguration.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/config/VelocityConfiguration.java @@ -318,6 +318,11 @@ public class VelocityConfiguration implements ProxyConfig { return advanced.getReadTimeout(); } + @Override + public int getInitialReadTimeout() { + return advanced.getInitialReadTimeout(); + } + public boolean isProxyProtocol() { return advanced.isProxyProtocol(); } @@ -592,6 +597,7 @@ public class VelocityConfiguration implements ProxyConfig { private boolean failoverOnUnexpectedServerDisconnect = true; private boolean announceProxyCommands = true; private boolean logCommandExecutions = false; + private int initialReadTimeout = 3000; private Advanced() { } @@ -611,6 +617,7 @@ public class VelocityConfiguration implements ProxyConfig { .getOrElse("failover-on-unexpected-server-disconnect", true); this.announceProxyCommands = config.getOrElse("announce-proxy-commands", true); this.logCommandExecutions = config.getOrElse("log-command-executions", false); + this.initialReadTimeout = config.getIntOrElse("initial-read-timeout", 3000); } } @@ -662,6 +669,10 @@ public class VelocityConfiguration implements ProxyConfig { return logCommandExecutions; } + public int getInitialReadTimeout() { + return initialReadTimeout; + } + @Override public String toString() { return "Advanced{" diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/LoginSessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/LoginSessionHandler.java index b49d46a7c..8061710b8 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/LoginSessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/LoginSessionHandler.java @@ -25,6 +25,7 @@ import com.velocitypowered.proxy.config.PlayerInfoForwarding; import com.velocitypowered.proxy.config.VelocityConfiguration; import com.velocitypowered.proxy.connection.MinecraftConnection; import com.velocitypowered.proxy.connection.MinecraftSessionHandler; +import com.velocitypowered.proxy.network.Connections; import com.velocitypowered.proxy.protocol.StateRegistry; import com.velocitypowered.proxy.protocol.packet.Disconnect; import com.velocitypowered.proxy.protocol.packet.EncryptionRequest; @@ -34,6 +35,7 @@ import com.velocitypowered.proxy.protocol.packet.ServerLoginSuccess; import com.velocitypowered.proxy.protocol.packet.SetCompression; import com.velocitypowered.proxy.util.VelocityMessages; import io.netty.buffer.ByteBuf; +import io.netty.handler.timeout.ReadTimeoutHandler; import java.net.InetSocketAddress; import java.security.GeneralSecurityException; import java.security.KeyPair; @@ -43,6 +45,7 @@ import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.TimeUnit; import net.kyori.adventure.text.Component; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -198,6 +201,12 @@ public class LoginSessionHandler implements MinecraftSessionHandler { } private void initializePlayer(GameProfile profile, boolean onlineMode) { + // Restore normal timeout for connection. + mcConnection.getChannel().pipeline() + .replace(Connections.READ_TIMEOUT, Connections.READ_TIMEOUT, + new ReadTimeoutHandler(server.getConfiguration().getReadTimeout(), + TimeUnit.MILLISECONDS)); + // Some connection types may need to alter the game profile. profile = mcConnection.getType().addGameProfileTokensIfRequired(profile, server.getConfiguration().getPlayerInfoForwardingMode()); diff --git a/proxy/src/main/java/com/velocitypowered/proxy/network/ServerChannelInitializer.java b/proxy/src/main/java/com/velocitypowered/proxy/network/ServerChannelInitializer.java index 64d2ec835..1f97fd1ec 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/network/ServerChannelInitializer.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/network/ServerChannelInitializer.java @@ -37,7 +37,7 @@ public class ServerChannelInitializer extends ChannelInitializer { protected void initChannel(final Channel ch) { ch.pipeline() .addLast(READ_TIMEOUT, - new ReadTimeoutHandler(this.server.getConfiguration().getReadTimeout(), + new ReadTimeoutHandler(this.server.getConfiguration().getInitialReadTimeout(), TimeUnit.MILLISECONDS)) .addLast(LEGACY_PING_DECODER, new LegacyPingDecoder()) .addLast(FRAME_DECODER, new MinecraftVarintFrameDecoder()) diff --git a/proxy/src/main/resources/default-velocity.toml b/proxy/src/main/resources/default-velocity.toml index 237b15687..aad435f11 100644 --- a/proxy/src/main/resources/default-velocity.toml +++ b/proxy/src/main/resources/default-velocity.toml @@ -105,6 +105,9 @@ connection-timeout = 5000 # Specify a read timeout for connections here. The default is 30 seconds. read-timeout = 30000 +# Specify an initial read timeout for connections here. The default is 3 seconds. +initial-read-timeout = 3000 + # Enables compatibility with HAProxy. proxy-protocol = false