diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/LoginSessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/LoginSessionHandler.java index cf3e776b5..24145a4f2 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/LoginSessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/LoginSessionHandler.java @@ -15,7 +15,6 @@ import com.velocitypowered.proxy.protocol.packet.*; import com.velocitypowered.proxy.connection.MinecraftSessionHandler; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; -import io.netty.channel.ChannelPipeline; import net.kyori.text.TextComponent; import javax.crypto.Mac; @@ -23,27 +22,16 @@ import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; +import java.util.concurrent.CompletableFuture; public class LoginSessionHandler implements MinecraftSessionHandler { private final ServerConnection connection; - private ScheduledFuture forwardingCheckTask; + private boolean informationForwarded; public LoginSessionHandler(ServerConnection connection) { this.connection = connection; } - @Override - public void activated() { - if (VelocityServer.getServer().getConfiguration().getPlayerInfoForwardingMode() == PlayerInfoForwarding.MODERN) { - forwardingCheckTask = connection.getMinecraftConnection().getChannel().eventLoop().schedule(() -> { - connection.getProxyPlayer().handleConnectionException(connection.getServerInfo(), - TextComponent.of("Your server did not send the forwarding request in time. Is it set up correctly?")); - }, 1, TimeUnit.SECONDS); - } - } - @Override public void handle(MinecraftPacket packet) { if (packet instanceof EncryptionRequest) { @@ -60,11 +48,7 @@ public class LoginSessionHandler implements MinecraftSessionHandler { connection.getProxyPlayer().getRemoteAddress().getHostString(), connection.getProxyPlayer().getProfile())); connection.getMinecraftConnection().write(response); - cancelForwardingCheck(); - - ServerLogin login = new ServerLogin(); - login.setUsername(connection.getProxyPlayer().getUsername()); - connection.getMinecraftConnection().write(login); + informationForwarded = true; } else { // Don't understand LoginPluginResponse response = new LoginPluginResponse(); @@ -75,16 +59,21 @@ public class LoginSessionHandler implements MinecraftSessionHandler { } } else if (packet instanceof Disconnect) { Disconnect disconnect = (Disconnect) packet; - connection.disconnect(); - // Do we have an outstanding notification? If so, fulfill it. doNotify(ConnectionRequestResults.forDisconnect(disconnect)); - - connection.getProxyPlayer().handleConnectionException(connection.getServerInfo(), disconnect); + connection.disconnect(); } else if (packet instanceof SetCompression) { SetCompression sc = (SetCompression) packet; connection.getMinecraftConnection().setCompressionThreshold(sc.getThreshold()); } else if (packet instanceof ServerLoginSuccess) { + if (VelocityServer.getServer().getConfiguration().getPlayerInfoForwardingMode() == PlayerInfoForwarding.MODERN && + !informationForwarded) { + doNotify(ConnectionRequestResults.forDisconnect( + TextComponent.of("Your server did not send a forwarding request to the proxy. Is it set up correctly?"))); + connection.disconnect(); + return; + } + // The player has been logged on to the backend server. connection.getMinecraftConnection().setState(StateRegistry.PLAY); ServerConnection existingConnection = connection.getProxyPlayer().getConnectedServer(); @@ -96,37 +85,26 @@ public class LoginSessionHandler implements MinecraftSessionHandler { existingConnection.disconnect(); } - // Do we have an outstanding notification? If so, fulfill it. doNotify(ConnectionRequestResults.SUCCESSFUL); - connection.getMinecraftConnection().setSessionHandler(new BackendPlaySessionHandler(connection)); connection.getProxyPlayer().setConnectedServer(connection); } } - @Override - public void deactivated() { - cancelForwardingCheck(); - } - @Override public void exception(Throwable throwable) { - connection.getProxyPlayer().handleConnectionException(connection.getServerInfo(), throwable); - } - - private void doNotify(ConnectionRequestBuilder.Result result) { - ChannelPipeline pipeline = connection.getMinecraftConnection().getChannel().pipeline(); - ServerConnection.ConnectionNotifier n = pipeline.get(ServerConnection.ConnectionNotifier.class); - if (n != null) { - n.getResult().complete(result); - pipeline.remove(ServerConnection.ConnectionNotifier.class); + CompletableFuture future = connection.getMinecraftConnection().getChannel() + .attr(ServerConnection.CONNECTION_NOTIFIER).getAndSet(null); + if (future != null) { + future.completeExceptionally(throwable); } } - private void cancelForwardingCheck() { - if (forwardingCheckTask != null) { - forwardingCheckTask.cancel(false); - forwardingCheckTask = null; + private void doNotify(ConnectionRequestBuilder.Result result) { + CompletableFuture future = connection.getMinecraftConnection().getChannel() + .attr(ServerConnection.CONNECTION_NOTIFIER).getAndSet(null); + if (future != null) { + future.complete(result); } } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/ServerConnection.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/ServerConnection.java index 36b56366c..98e4cd72d 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/ServerConnection.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/ServerConnection.java @@ -18,6 +18,7 @@ import com.velocitypowered.proxy.VelocityServer; import com.velocitypowered.proxy.connection.client.ConnectedPlayer; import io.netty.channel.*; import io.netty.handler.timeout.ReadTimeoutHandler; +import io.netty.util.AttributeKey; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; @@ -31,7 +32,8 @@ import static com.velocitypowered.network.Connections.READ_TIMEOUT; import static com.velocitypowered.network.Connections.SERVER_READ_TIMEOUT_SECONDS; public class ServerConnection implements MinecraftConnectionAssociation { - static final String CONNECTION_NOTIFIER = "connection-notifier"; + static final AttributeKey> CONNECTION_NOTIFIER = + AttributeKey.newInstance("connection-notification-result"); private final ServerInfo serverInfo; private final ConnectedPlayer proxyPlayer; @@ -55,9 +57,9 @@ public class ServerConnection implements MinecraftConnectionAssociation { .addLast(FRAME_DECODER, new MinecraftVarintFrameDecoder()) .addLast(FRAME_ENCODER, MinecraftVarintLengthEncoder.INSTANCE) .addLast(MINECRAFT_DECODER, new MinecraftDecoder(ProtocolConstants.Direction.CLIENTBOUND)) - .addLast(MINECRAFT_ENCODER, new MinecraftEncoder(ProtocolConstants.Direction.SERVERBOUND)) - .addLast(CONNECTION_NOTIFIER, new ConnectionNotifier(result)); + .addLast(MINECRAFT_ENCODER, new MinecraftEncoder(ProtocolConstants.Direction.SERVERBOUND)); + ch.attr(CONNECTION_NOTIFIER).set(result); MinecraftConnection connection = new MinecraftConnection(ch); connection.setState(StateRegistry.HANDSHAKE); connection.setAssociation(ServerConnection.this); @@ -93,7 +95,7 @@ public class ServerConnection implements MinecraftConnectionAssociation { } private void startHandshake() { - PlayerInfoForwarding forwardingMode = VelocityServer.getServer().getConfiguration().getPlayerInfoForwardingMode(); + PlayerInfoForwarding forwardingMode = VelocityServer.getServer().getConfiguration().getPlayerInfoForwardingMode(); // Initiate a handshake. Handshake handshake = new Handshake(); @@ -111,12 +113,9 @@ public class ServerConnection implements MinecraftConnectionAssociation { minecraftConnection.setProtocolVersion(protocolVersion); minecraftConnection.setState(StateRegistry.LOGIN); - // Send the server login packet for <=1.12.2 and for 1.13+ servers not using "modern" forwarding. - if (protocolVersion <= ProtocolConstants.MINECRAFT_1_12_2 || forwardingMode != PlayerInfoForwarding.MODERN) { - ServerLogin login = new ServerLogin(); - login.setUsername(proxyPlayer.getUsername()); - minecraftConnection.write(login); - } + ServerLogin login = new ServerLogin(); + login.setUsername(proxyPlayer.getUsername()); + minecraftConnection.write(login); } public ConnectedPlayer getProxyPlayer() { @@ -140,25 +139,4 @@ public class ServerConnection implements MinecraftConnectionAssociation { public String toString() { return "[server connection] " + proxyPlayer.getProfile().getName() + " -> " + serverInfo.getName(); } - - static class ConnectionNotifier extends ChannelInboundHandlerAdapter { - private final CompletableFuture result; - - public ConnectionNotifier(CompletableFuture result) { - this.result = result; - } - - public CompletableFuture getResult() { - return result; - } - - public void onComplete() { - result.complete(ConnectionRequestResults.SUCCESSFUL); - } - - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - result.completeExceptionally(cause); - } - } } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java index a10681fa8..2cf2b887f 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java @@ -247,7 +247,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { @Override public void fireAndForget() { connect() - .whenComplete((status, throwable) -> { + .whenCompleteAsync((status, throwable) -> { if (throwable != null) { handleConnectionException(info, throwable); return; @@ -267,7 +267,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { handleConnectionException(info, Disconnect.create(status.getReason().orElse(ConnectionMessages.INTERNAL_SERVER_CONNECTION_ERROR))); break; } - }); + }, connection.getChannel().eventLoop()); } } } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/util/ConnectionRequestResults.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/util/ConnectionRequestResults.java index 8e2d8ec8d..0f6811fde 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/util/ConnectionRequestResults.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/util/ConnectionRequestResults.java @@ -3,6 +3,7 @@ package com.velocitypowered.proxy.connection.util; import com.velocitypowered.api.proxy.ConnectionRequestBuilder; import com.velocitypowered.proxy.protocol.packet.Disconnect; import net.kyori.text.Component; +import net.kyori.text.TextComponent; import net.kyori.text.serializer.ComponentSerializers; import java.util.Optional; @@ -42,4 +43,18 @@ public class ConnectionRequestResults { } }; } + + public static ConnectionRequestBuilder.Result forDisconnect(TextComponent component) { + return new ConnectionRequestBuilder.Result() { + @Override + public ConnectionRequestBuilder.Status getStatus() { + return ConnectionRequestBuilder.Status.SERVER_DISCONNECTED; + } + + @Override + public Optional getReason() { + return Optional.of(component); + } + }; + } }