From 2f5ca386a6022f897bbc8bd7c26bc4446ea60f5d Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Tue, 31 Jul 2018 00:47:05 -0400 Subject: [PATCH] Actually fix the login plugin messaging --- .../proxy/config/VelocityConfiguration.java | 3 - .../proxy/connection/MinecraftConnection.java | 3 + .../connection/MinecraftSessionHandler.java | 4 + .../backend/BackendPlaySessionHandler.java | 4 +- .../backend/LoginSessionHandler.java | 90 +++++++++++++++---- .../connection/backend/ServerConnection.java | 75 ++++------------ .../client/ClientPlaySessionHandler.java | 18 ++-- .../connection/client/ConnectedPlayer.java | 15 +++- .../client/InitialConnectSessionHandler.java | 2 +- .../client/LoginSessionHandler.java | 27 +++--- .../proxy/protocol/StateRegistry.java | 4 +- 11 files changed, 143 insertions(+), 102 deletions(-) diff --git a/src/main/java/com/velocitypowered/proxy/config/VelocityConfiguration.java b/src/main/java/com/velocitypowered/proxy/config/VelocityConfiguration.java index 49ef6771a..cd1839d4e 100644 --- a/src/main/java/com/velocitypowered/proxy/config/VelocityConfiguration.java +++ b/src/main/java/com/velocitypowered/proxy/config/VelocityConfiguration.java @@ -67,9 +67,6 @@ public class VelocityConfiguration { case NONE: logger.info("IP forwarding is disabled! All players will appear to be connecting from the proxy and will have offline-mode UUIDs."); break; - case MODERN: - logger.warn("Modern IP forwarding is not currently implemented."); - break; } if (servers.isEmpty()) { diff --git a/src/main/java/com/velocitypowered/proxy/connection/MinecraftConnection.java b/src/main/java/com/velocitypowered/proxy/connection/MinecraftConnection.java index 9f59adb1b..d5b9023fb 100644 --- a/src/main/java/com/velocitypowered/proxy/connection/MinecraftConnection.java +++ b/src/main/java/com/velocitypowered/proxy/connection/MinecraftConnection.java @@ -171,6 +171,9 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter { } public void setSessionHandler(MinecraftSessionHandler sessionHandler) { + if (this.sessionHandler != null) { + this.sessionHandler.deactivated(); + } this.sessionHandler = sessionHandler; sessionHandler.activated(); } diff --git a/src/main/java/com/velocitypowered/proxy/connection/MinecraftSessionHandler.java b/src/main/java/com/velocitypowered/proxy/connection/MinecraftSessionHandler.java index 96d80b021..d445fb51c 100644 --- a/src/main/java/com/velocitypowered/proxy/connection/MinecraftSessionHandler.java +++ b/src/main/java/com/velocitypowered/proxy/connection/MinecraftSessionHandler.java @@ -22,6 +22,10 @@ public interface MinecraftSessionHandler { } + default void deactivated() { + + } + default void exception(Throwable throwable) { } diff --git a/src/main/java/com/velocitypowered/proxy/connection/backend/BackendPlaySessionHandler.java b/src/main/java/com/velocitypowered/proxy/connection/backend/BackendPlaySessionHandler.java index e62ab32bf..598157937 100644 --- a/src/main/java/com/velocitypowered/proxy/connection/backend/BackendPlaySessionHandler.java +++ b/src/main/java/com/velocitypowered/proxy/connection/backend/BackendPlaySessionHandler.java @@ -22,7 +22,7 @@ public class BackendPlaySessionHandler implements MinecraftSessionHandler { (ClientPlaySessionHandler) connection.getProxyPlayer().getConnection().getSessionHandler(); if (packet instanceof KeepAlive) { // Forward onto the server - connection.getChannel().write(packet); + connection.getMinecraftConnection().write(packet); } else if (packet instanceof Disconnect) { Disconnect original = (Disconnect) packet; connection.getProxyPlayer().handleConnectionException(connection.getServerInfo(), original); @@ -92,7 +92,7 @@ public class BackendPlaySessionHandler implements MinecraftSessionHandler { private boolean canForwardPluginMessage(PluginMessage message) { ClientPlaySessionHandler playerHandler = (ClientPlaySessionHandler) connection.getProxyPlayer().getConnection().getSessionHandler(); - if (connection.getChannel().getProtocolVersion() <= ProtocolConstants.MINECRAFT_1_12_2) { + if (connection.getMinecraftConnection().getProtocolVersion() <= ProtocolConstants.MINECRAFT_1_12_2) { return message.getChannel().startsWith("MC|") || playerHandler.getClientPluginMsgChannels().contains(message.getChannel()); } else { diff --git a/src/main/java/com/velocitypowered/proxy/connection/backend/LoginSessionHandler.java b/src/main/java/com/velocitypowered/proxy/connection/backend/LoginSessionHandler.java index feee8649a..997ba4c5c 100644 --- a/src/main/java/com/velocitypowered/proxy/connection/backend/LoginSessionHandler.java +++ b/src/main/java/com/velocitypowered/proxy/connection/backend/LoginSessionHandler.java @@ -1,29 +1,69 @@ package com.velocitypowered.proxy.connection.backend; +import com.velocitypowered.proxy.VelocityServer; +import com.velocitypowered.proxy.config.IPForwardingMode; +import com.velocitypowered.proxy.connection.VelocityConstants; import com.velocitypowered.proxy.connection.client.ClientPlaySessionHandler; +import com.velocitypowered.proxy.data.GameProfile; import com.velocitypowered.proxy.protocol.MinecraftPacket; +import com.velocitypowered.proxy.protocol.ProtocolUtils; import com.velocitypowered.proxy.protocol.StateRegistry; import com.velocitypowered.proxy.protocol.packets.*; import com.velocitypowered.proxy.connection.MinecraftSessionHandler; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import net.kyori.text.TextComponent; + +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; public class LoginSessionHandler implements MinecraftSessionHandler { private final ServerConnection connection; - private int forwardingPacketId = -1; + private ScheduledFuture modernForwardingNotice; public LoginSessionHandler(ServerConnection connection) { this.connection = connection; } + @Override + public void activated() { + if (VelocityServer.getServer().getConfiguration().getIpForwardingMode() == IPForwardingMode.MODERN) { + modernForwardingNotice = 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) { throw new IllegalStateException("Backend server is online-mode!"); - } else if (packet instanceof LoginPluginResponse) { - LoginPluginResponse lpr = (LoginPluginResponse) packet; - if (lpr.getId() == forwardingPacketId) { - if (!lpr.isSuccess()) { - throw new IllegalStateException("Unable to forward player information to server! Is it configured properly?"); + } else if (packet instanceof LoginPluginMessage) { + LoginPluginMessage message = (LoginPluginMessage) packet; + if (VelocityServer.getServer().getConfiguration().getIpForwardingMode() == IPForwardingMode.MODERN && + message.getChannel().equals(VelocityConstants.VELOCITY_IP_FORWARDING_CHANNEL)) { + LoginPluginResponse response = new LoginPluginResponse(); + response.setSuccess(true); + response.setId(message.getId()); + response.setData(createForwardingData(connection.getProxyPlayer().getRemoteAddress().getHostString(), + connection.getProxyPlayer().getProfile())); + connection.getMinecraftConnection().write(response); + if (modernForwardingNotice != null) { + modernForwardingNotice.cancel(false); + modernForwardingNotice = null; } + + ServerLogin login = new ServerLogin(); + login.setUsername(connection.getProxyPlayer().getUsername()); + connection.getMinecraftConnection().write(login); + } else { + // Don't understand + LoginPluginResponse response = new LoginPluginResponse(); + response.setSuccess(false); + response.setId(message.getId()); + response.setData(Unpooled.EMPTY_BUFFER); + connection.getMinecraftConnection().write(response); } } else if (packet instanceof Disconnect) { Disconnect disconnect = (Disconnect) packet; @@ -31,10 +71,10 @@ public class LoginSessionHandler implements MinecraftSessionHandler { connection.getProxyPlayer().handleConnectionException(connection.getServerInfo(), disconnect); } else if (packet instanceof SetCompression) { SetCompression sc = (SetCompression) packet; - connection.getChannel().setCompressionThreshold(sc.getThreshold()); + connection.getMinecraftConnection().setCompressionThreshold(sc.getThreshold()); } else if (packet instanceof ServerLoginSuccess) { // The player has been logged on to the backend server. - connection.getChannel().setState(StateRegistry.PLAY); + connection.getMinecraftConnection().setState(StateRegistry.PLAY); ServerConnection existingConnection = connection.getProxyPlayer().getConnectedServer(); if (existingConnection == null) { // Strap on the play session handler @@ -43,21 +83,41 @@ public class LoginSessionHandler implements MinecraftSessionHandler { // The previous server connection should become obsolete. existingConnection.disconnect(); } - connection.getChannel().setSessionHandler(new BackendPlaySessionHandler(connection)); + connection.getMinecraftConnection().setSessionHandler(new BackendPlaySessionHandler(connection)); connection.getProxyPlayer().setConnectedServer(connection); } } + @Override + public void deactivated() { + if (modernForwardingNotice != null) { + modernForwardingNotice.cancel(false); + modernForwardingNotice = null; + } + } + @Override public void exception(Throwable throwable) { connection.getProxyPlayer().handleConnectionException(connection.getServerInfo(), throwable); } - public int getForwardingPacketId() { - return forwardingPacketId; - } - - public void setForwardingPacketId(int forwardingPacketId) { - this.forwardingPacketId = forwardingPacketId; + private static ByteBuf createForwardingData(String address, GameProfile profile) { + ByteBuf buf = Unpooled.buffer(); + ProtocolUtils.writeString(buf, address); + ProtocolUtils.writeString(buf, profile.getName()); + ProtocolUtils.writeUuid(buf, profile.idAsUuid()); + ProtocolUtils.writeVarInt(buf, profile.getProperties().size()); + for (GameProfile.Property property : profile.getProperties()) { + ProtocolUtils.writeString(buf, property.getName()); + ProtocolUtils.writeString(buf, property.getValue()); + String signature = property.getSignature(); + if (signature != null) { + buf.writeBoolean(true); + ProtocolUtils.writeString(buf, signature); + } else { + buf.writeBoolean(false); + } + } + return buf; } } diff --git a/src/main/java/com/velocitypowered/proxy/connection/backend/ServerConnection.java b/src/main/java/com/velocitypowered/proxy/connection/backend/ServerConnection.java index 263390d59..54dcbf74d 100644 --- a/src/main/java/com/velocitypowered/proxy/connection/backend/ServerConnection.java +++ b/src/main/java/com/velocitypowered/proxy/connection/backend/ServerConnection.java @@ -2,28 +2,21 @@ package com.velocitypowered.proxy.connection.backend; import com.velocitypowered.proxy.config.IPForwardingMode; import com.velocitypowered.proxy.connection.MinecraftConnectionAssociation; -import com.velocitypowered.proxy.connection.VelocityConstants; -import com.velocitypowered.proxy.data.GameProfile; import com.velocitypowered.proxy.protocol.ProtocolConstants; -import com.velocitypowered.proxy.protocol.ProtocolUtils; import com.velocitypowered.proxy.protocol.netty.MinecraftDecoder; import com.velocitypowered.proxy.protocol.netty.MinecraftEncoder; import com.velocitypowered.proxy.protocol.netty.MinecraftVarintFrameDecoder; import com.velocitypowered.proxy.protocol.netty.MinecraftVarintLengthEncoder; import com.velocitypowered.proxy.protocol.packets.Handshake; -import com.velocitypowered.proxy.protocol.packets.LoginPluginMessage; import com.velocitypowered.proxy.protocol.packets.ServerLogin; import com.velocitypowered.proxy.connection.MinecraftConnection; import com.velocitypowered.proxy.protocol.StateRegistry; import com.velocitypowered.proxy.data.ServerInfo; import com.velocitypowered.proxy.VelocityServer; import com.velocitypowered.proxy.connection.client.ConnectedPlayer; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; import io.netty.channel.*; import io.netty.handler.timeout.ReadTimeoutHandler; -import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; import static com.velocitypowered.network.Connections.FRAME_DECODER; @@ -38,7 +31,7 @@ public class ServerConnection implements MinecraftConnectionAssociation { private final ServerInfo serverInfo; private final ConnectedPlayer proxyPlayer; private final VelocityServer server; - private MinecraftConnection channel; + private MinecraftConnection minecraftConnection; public ServerConnection(ServerInfo target, ConnectedPlayer proxyPlayer, VelocityServer server) { this.serverInfo = target; @@ -60,7 +53,6 @@ public class ServerConnection implements MinecraftConnectionAssociation { MinecraftConnection connection = new MinecraftConnection(ch); connection.setState(StateRegistry.HANDSHAKE); - connection.setSessionHandler(new LoginSessionHandler(ServerConnection.this)); connection.setAssociation(ServerConnection.this); ch.pipeline().addLast(HANDLER, connection); } @@ -70,9 +62,10 @@ public class ServerConnection implements MinecraftConnectionAssociation { @Override public void operationComplete(ChannelFuture future) throws Exception { if (future.isSuccess()) { - channel = future.channel().pipeline().get(MinecraftConnection.class); + minecraftConnection = future.channel().pipeline().get(MinecraftConnection.class); // Kick off the connection process + minecraftConnection.setSessionHandler(new LoginSessionHandler(ServerConnection.this)); startHandshake(); } else { proxyPlayer.handleConnectionException(serverInfo, future.cause()); @@ -102,43 +95,27 @@ public class ServerConnection implements MinecraftConnectionAssociation { handshake.setServerAddress(serverInfo.getAddress().getHostString()); } handshake.setPort(serverInfo.getAddress().getPort()); - channel.write(handshake); + minecraftConnection.write(handshake); int protocolVersion = proxyPlayer.getConnection().getProtocolVersion(); - channel.setProtocolVersion(protocolVersion); - channel.setState(StateRegistry.LOGIN); + minecraftConnection.setProtocolVersion(protocolVersion); + minecraftConnection.setState(StateRegistry.LOGIN); - // 1.13 stuff - if (protocolVersion >= ProtocolConstants.MINECRAFT_1_13) { - if (VelocityServer.getServer().getConfiguration().getIpForwardingMode() == IPForwardingMode.MODERN) { - // Velocity's IP forwarding includes the player's IP address and their game profile. - GameProfile profile = proxyPlayer.getProfile(); - ByteBuf buf = createForwardingData(proxyPlayer.getRemoteAddress().getHostString(), profile); - - // Send the message on - LoginPluginMessage forwarding = new LoginPluginMessage(); - forwarding.setId(ThreadLocalRandom.current().nextInt()); - forwarding.setChannel(VelocityConstants.VELOCITY_IP_FORWARDING_CHANNEL); - forwarding.setData(buf); - - LoginSessionHandler lsh = (LoginSessionHandler) channel.getSessionHandler(); - lsh.setForwardingPacketId(forwarding.getId()); - channel.write(forwarding); - } + // 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 || + VelocityServer.getServer().getConfiguration().getIpForwardingMode() != IPForwardingMode.MODERN) { + ServerLogin login = new ServerLogin(); + login.setUsername(proxyPlayer.getUsername()); + minecraftConnection.write(login); } - - // Login - ServerLogin login = new ServerLogin(); - login.setUsername(proxyPlayer.getUsername()); - channel.write(login); } public ConnectedPlayer getProxyPlayer() { return proxyPlayer; } - public MinecraftConnection getChannel() { - return channel; + public MinecraftConnection getMinecraftConnection() { + return minecraftConnection; } public ServerInfo getServerInfo() { @@ -146,32 +123,12 @@ public class ServerConnection implements MinecraftConnectionAssociation { } public void disconnect() { - channel.close(); - channel = null; + minecraftConnection.close(); + minecraftConnection = null; } @Override public String toString() { return "[server connection] " + proxyPlayer.getProfile().getName() + " -> " + serverInfo.getName(); } - - private static ByteBuf createForwardingData(String address, GameProfile profile) { - ByteBuf buf = Unpooled.buffer(); - ProtocolUtils.writeString(buf, address); - ProtocolUtils.writeString(buf, profile.getName()); - ProtocolUtils.writeUuid(buf, profile.idAsUuid()); - ProtocolUtils.writeVarInt(buf, profile.getProperties().size()); - for (GameProfile.Property property : profile.getProperties()) { - ProtocolUtils.writeString(buf, property.getName()); - ProtocolUtils.writeString(buf, property.getValue()); - String signature = property.getSignature(); - if (signature != null) { - buf.writeBoolean(true); - ProtocolUtils.writeString(buf, signature); - } else { - buf.writeBoolean(false); - } - } - return buf; - } } diff --git a/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java b/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java index 957ee96e9..a665a7b21 100644 --- a/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java +++ b/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java @@ -93,18 +93,18 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler { } // If we don't want to handle this packet, just forward it on. - player.getConnectedServer().getChannel().write(packet); + player.getConnectedServer().getMinecraftConnection().write(packet); } @Override public void handleUnknown(ByteBuf buf) { ByteBuf remapped = idRemapper.remap(buf, ProtocolConstants.Direction.SERVERBOUND); - player.getConnectedServer().getChannel().write(remapped); + player.getConnectedServer().getMinecraftConnection().write(remapped); } @Override public void disconnected() { - player.getConnectedServer().disconnect(); + player.teardown(); if (pingTask != null && !pingTask.isCancelled()) { pingTask.cancel(false); @@ -150,7 +150,7 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler { // Resend client settings packet to remote server if we have it, this preserves client settings across // transitions. if (player.getClientSettings() != null) { - player.getConnectedServer().getChannel().delayedWrite(player.getClientSettings()); + player.getConnectedServer().getMinecraftConnection().delayedWrite(player.getClientSettings()); } // Remove old boss bars. @@ -169,19 +169,19 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler { if (!clientPluginMsgChannels.isEmpty()) { String channel = player.getConnection().getProtocolVersion() >= ProtocolConstants.MINECRAFT_1_13 ? "minecraft:register" : "REGISTER"; - player.getConnectedServer().getChannel().delayedWrite( + player.getConnectedServer().getMinecraftConnection().delayedWrite( PluginMessageUtil.constructChannelsPacket(channel, clientPluginMsgChannels)); } // Tell the server the client's brand if (brandMessage != null) { brandMessage.getData().retain(); - player.getConnectedServer().getChannel().delayedWrite(brandMessage); + player.getConnectedServer().getMinecraftConnection().delayedWrite(brandMessage); } // Flush everything player.getConnection().flush(); - player.getConnectedServer().getChannel().flush(); + player.getConnectedServer().getMinecraftConnection().flush(); } public void setCurrentDimension(int currentDimension) { @@ -213,7 +213,7 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler { if (actuallyRegistered.size() > 0) { logger.info("Rewritten register packet: {}", actuallyRegistered); PluginMessage newRegisterPacket = PluginMessageUtil.constructChannelsPacket(packet.getChannel(), actuallyRegistered); - player.getConnectedServer().getChannel().write(newRegisterPacket); + player.getConnectedServer().getMinecraftConnection().write(newRegisterPacket); } return; @@ -242,7 +242,7 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler { packet.getData().retain(); } - player.getConnectedServer().getChannel().write(packet); + player.getConnectedServer().getMinecraftConnection().write(packet); } finally { ReferenceCountUtil.release(original.getData()); } diff --git a/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java b/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java index 4d2e8a1bc..b96560510 100644 --- a/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java +++ b/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java @@ -21,6 +21,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import java.net.InetSocketAddress; +import java.util.Collection; import java.util.List; import java.util.Optional; import java.util.UUID; @@ -35,6 +36,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation { private int tryIndex = 0; private ServerConnection connectedServer; private ClientSettings clientSettings; + private ServerConnection connectionInFlight; public ConnectedPlayer(GameProfile profile, MinecraftConnection connection) { this.profile = profile; @@ -101,7 +103,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation { handleConnectionException(info, disconnectReason); } - private void handleConnectionException(ServerInfo info, Component disconnectReason) { + public void handleConnectionException(ServerInfo info, Component disconnectReason) { if (connectedServer == null || connectedServer.getServerInfo().equals(info)) { // The player isn't yet connected to a server or they are already connected to the server // they're disconnected from. @@ -124,7 +126,9 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation { public void connect(ServerInfo info) { Preconditions.checkNotNull(info, "info"); + Preconditions.checkState(connectionInFlight == null, "A connection is already active!"); ServerConnection connection = new ServerConnection(info, this, VelocityServer.getServer()); + connectionInFlight = connection; connection.connect(); } @@ -139,6 +143,15 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation { connection.closeWith(Disconnect.create(reason)); } + public void teardown() { + if (connectionInFlight != null) { + connectionInFlight.disconnect(); + } + if (connectedServer != null) { + connectedServer.disconnect(); + } + } + @Override public String toString() { return "[connected player] " + getProfile().getName() + " (" + getRemoteAddress() + ")"; diff --git a/src/main/java/com/velocitypowered/proxy/connection/client/InitialConnectSessionHandler.java b/src/main/java/com/velocitypowered/proxy/connection/client/InitialConnectSessionHandler.java index 26a13c6a5..64273473a 100644 --- a/src/main/java/com/velocitypowered/proxy/connection/client/InitialConnectSessionHandler.java +++ b/src/main/java/com/velocitypowered/proxy/connection/client/InitialConnectSessionHandler.java @@ -18,6 +18,6 @@ public class InitialConnectSessionHandler implements MinecraftSessionHandler { @Override public void disconnected() { // the user cancelled the login process - player.getConnectedServer().disconnect(); + player.teardown(); } } diff --git a/src/main/java/com/velocitypowered/proxy/connection/client/LoginSessionHandler.java b/src/main/java/com/velocitypowered/proxy/connection/client/LoginSessionHandler.java index c8b4637c4..7c7fc9eec 100644 --- a/src/main/java/com/velocitypowered/proxy/connection/client/LoginSessionHandler.java +++ b/src/main/java/com/velocitypowered/proxy/connection/client/LoginSessionHandler.java @@ -4,6 +4,7 @@ import com.google.common.base.Preconditions; import com.velocitypowered.proxy.connection.VelocityConstants; import com.velocitypowered.proxy.data.GameProfile; import com.velocitypowered.proxy.protocol.MinecraftPacket; +import com.velocitypowered.proxy.protocol.ProtocolConstants; import com.velocitypowered.proxy.protocol.StateRegistry; import com.velocitypowered.proxy.protocol.packets.*; import com.velocitypowered.proxy.connection.MinecraftConnection; @@ -35,27 +36,33 @@ public class LoginSessionHandler implements MinecraftSessionHandler { private final MinecraftConnection inbound; private ServerLogin login; private byte[] verify; + private int playerInfoId; public LoginSessionHandler(MinecraftConnection inbound) { this.inbound = Preconditions.checkNotNull(inbound, "inbound"); } + @Override + public void activated() { + if (inbound.getProtocolVersion() >= ProtocolConstants.MINECRAFT_1_13) { + LoginPluginMessage message = new LoginPluginMessage(); + playerInfoId = ThreadLocalRandom.current().nextInt(); + message.setId(playerInfoId); + message.setChannel(VelocityConstants.VELOCITY_IP_FORWARDING_CHANNEL); + message.setData(Unpooled.EMPTY_BUFFER); + inbound.write(message); + } + } + @Override public void handle(MinecraftPacket packet) throws Exception { - if (packet instanceof LoginPluginMessage) { - LoginPluginMessage lpm = (LoginPluginMessage) packet; - if (lpm.getChannel().equals(VelocityConstants.VELOCITY_IP_FORWARDING_CHANNEL)) { + if (packet instanceof LoginPluginResponse) { + LoginPluginResponse lpr = (LoginPluginResponse) packet; + if (lpr.getId() == playerInfoId && lpr.isSuccess()) { // Uh oh, someone's trying to run Velocity behind Velocity. We don't want that happening. inbound.closeWith(Disconnect.create( TextComponent.of("Running Velocity behind Velocity isn't supported.", TextColor.RED) )); - } else { - // We don't know what this message is. - LoginPluginResponse response = new LoginPluginResponse(); - response.setId(lpm.getId()); - response.setSuccess(false); - response.setData(Unpooled.EMPTY_BUFFER); - inbound.write(response); } } else if (packet instanceof ServerLogin) { this.login = (ServerLogin) packet; diff --git a/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java b/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java index 8a5be3bd0..fc95b8f5b 100644 --- a/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java +++ b/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java @@ -108,7 +108,7 @@ public enum StateRegistry { genericMappings(0x00)); SERVERBOUND.register(EncryptionResponse.class, EncryptionResponse::new, genericMappings(0x01)); - SERVERBOUND.register(LoginPluginMessage.class, LoginPluginMessage::new, + SERVERBOUND.register(LoginPluginResponse.class, LoginPluginResponse::new, map(0x02, MINECRAFT_1_13)); CLIENTBOUND.register(Disconnect.class, Disconnect::new, @@ -119,7 +119,7 @@ public enum StateRegistry { genericMappings(0x02)); CLIENTBOUND.register(SetCompression.class, SetCompression::new, genericMappings(0x03)); - CLIENTBOUND.register(LoginPluginResponse.class, LoginPluginResponse::new, + CLIENTBOUND.register(LoginPluginMessage.class, LoginPluginMessage::new, map(0x04, MINECRAFT_1_13)); } };