3
0
Mirror von https://github.com/PaperMC/Velocity.git synchronisiert 2024-12-26 00:00:55 +01:00

Actually fix the login plugin messaging

Dieser Commit ist enthalten in:
Andrew Steinborn 2018-07-31 00:47:05 -04:00
Ursprung 2f5f93a427
Commit 2f5ca386a6
11 geänderte Dateien mit 143 neuen und 102 gelöschten Zeilen

Datei anzeigen

@ -67,9 +67,6 @@ public class VelocityConfiguration {
case NONE: case NONE:
logger.info("IP forwarding is disabled! All players will appear to be connecting from the proxy and will have offline-mode UUIDs."); logger.info("IP forwarding is disabled! All players will appear to be connecting from the proxy and will have offline-mode UUIDs.");
break; break;
case MODERN:
logger.warn("Modern IP forwarding is not currently implemented.");
break;
} }
if (servers.isEmpty()) { if (servers.isEmpty()) {

Datei anzeigen

@ -171,6 +171,9 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter {
} }
public void setSessionHandler(MinecraftSessionHandler sessionHandler) { public void setSessionHandler(MinecraftSessionHandler sessionHandler) {
if (this.sessionHandler != null) {
this.sessionHandler.deactivated();
}
this.sessionHandler = sessionHandler; this.sessionHandler = sessionHandler;
sessionHandler.activated(); sessionHandler.activated();
} }

Datei anzeigen

@ -22,6 +22,10 @@ public interface MinecraftSessionHandler {
} }
default void deactivated() {
}
default void exception(Throwable throwable) { default void exception(Throwable throwable) {
} }

Datei anzeigen

@ -22,7 +22,7 @@ public class BackendPlaySessionHandler implements MinecraftSessionHandler {
(ClientPlaySessionHandler) connection.getProxyPlayer().getConnection().getSessionHandler(); (ClientPlaySessionHandler) connection.getProxyPlayer().getConnection().getSessionHandler();
if (packet instanceof KeepAlive) { if (packet instanceof KeepAlive) {
// Forward onto the server // Forward onto the server
connection.getChannel().write(packet); connection.getMinecraftConnection().write(packet);
} else if (packet instanceof Disconnect) { } else if (packet instanceof Disconnect) {
Disconnect original = (Disconnect) packet; Disconnect original = (Disconnect) packet;
connection.getProxyPlayer().handleConnectionException(connection.getServerInfo(), original); connection.getProxyPlayer().handleConnectionException(connection.getServerInfo(), original);
@ -92,7 +92,7 @@ public class BackendPlaySessionHandler implements MinecraftSessionHandler {
private boolean canForwardPluginMessage(PluginMessage message) { private boolean canForwardPluginMessage(PluginMessage message) {
ClientPlaySessionHandler playerHandler = ClientPlaySessionHandler playerHandler =
(ClientPlaySessionHandler) connection.getProxyPlayer().getConnection().getSessionHandler(); (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|") || return message.getChannel().startsWith("MC|") ||
playerHandler.getClientPluginMsgChannels().contains(message.getChannel()); playerHandler.getClientPluginMsgChannels().contains(message.getChannel());
} else { } else {

Datei anzeigen

@ -1,29 +1,69 @@
package com.velocitypowered.proxy.connection.backend; 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.connection.client.ClientPlaySessionHandler;
import com.velocitypowered.proxy.data.GameProfile;
import com.velocitypowered.proxy.protocol.MinecraftPacket; import com.velocitypowered.proxy.protocol.MinecraftPacket;
import com.velocitypowered.proxy.protocol.ProtocolUtils;
import com.velocitypowered.proxy.protocol.StateRegistry; import com.velocitypowered.proxy.protocol.StateRegistry;
import com.velocitypowered.proxy.protocol.packets.*; import com.velocitypowered.proxy.protocol.packets.*;
import com.velocitypowered.proxy.connection.MinecraftSessionHandler; 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 { public class LoginSessionHandler implements MinecraftSessionHandler {
private final ServerConnection connection; private final ServerConnection connection;
private int forwardingPacketId = -1; private ScheduledFuture<?> modernForwardingNotice;
public LoginSessionHandler(ServerConnection connection) { public LoginSessionHandler(ServerConnection connection) {
this.connection = 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 @Override
public void handle(MinecraftPacket packet) { public void handle(MinecraftPacket packet) {
if (packet instanceof EncryptionRequest) { if (packet instanceof EncryptionRequest) {
throw new IllegalStateException("Backend server is online-mode!"); throw new IllegalStateException("Backend server is online-mode!");
} else if (packet instanceof LoginPluginResponse) { } else if (packet instanceof LoginPluginMessage) {
LoginPluginResponse lpr = (LoginPluginResponse) packet; LoginPluginMessage message = (LoginPluginMessage) packet;
if (lpr.getId() == forwardingPacketId) { if (VelocityServer.getServer().getConfiguration().getIpForwardingMode() == IPForwardingMode.MODERN &&
if (!lpr.isSuccess()) { message.getChannel().equals(VelocityConstants.VELOCITY_IP_FORWARDING_CHANNEL)) {
throw new IllegalStateException("Unable to forward player information to server! Is it configured properly?"); 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) { } else if (packet instanceof Disconnect) {
Disconnect disconnect = (Disconnect) packet; Disconnect disconnect = (Disconnect) packet;
@ -31,10 +71,10 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
connection.getProxyPlayer().handleConnectionException(connection.getServerInfo(), disconnect); connection.getProxyPlayer().handleConnectionException(connection.getServerInfo(), disconnect);
} else if (packet instanceof SetCompression) { } else if (packet instanceof SetCompression) {
SetCompression sc = (SetCompression) packet; SetCompression sc = (SetCompression) packet;
connection.getChannel().setCompressionThreshold(sc.getThreshold()); connection.getMinecraftConnection().setCompressionThreshold(sc.getThreshold());
} else if (packet instanceof ServerLoginSuccess) { } else if (packet instanceof ServerLoginSuccess) {
// The player has been logged on to the backend server. // 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(); ServerConnection existingConnection = connection.getProxyPlayer().getConnectedServer();
if (existingConnection == null) { if (existingConnection == null) {
// Strap on the play session handler // Strap on the play session handler
@ -43,21 +83,41 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
// The previous server connection should become obsolete. // The previous server connection should become obsolete.
existingConnection.disconnect(); existingConnection.disconnect();
} }
connection.getChannel().setSessionHandler(new BackendPlaySessionHandler(connection)); connection.getMinecraftConnection().setSessionHandler(new BackendPlaySessionHandler(connection));
connection.getProxyPlayer().setConnectedServer(connection); connection.getProxyPlayer().setConnectedServer(connection);
} }
} }
@Override
public void deactivated() {
if (modernForwardingNotice != null) {
modernForwardingNotice.cancel(false);
modernForwardingNotice = null;
}
}
@Override @Override
public void exception(Throwable throwable) { public void exception(Throwable throwable) {
connection.getProxyPlayer().handleConnectionException(connection.getServerInfo(), throwable); connection.getProxyPlayer().handleConnectionException(connection.getServerInfo(), throwable);
} }
public int getForwardingPacketId() { private static ByteBuf createForwardingData(String address, GameProfile profile) {
return forwardingPacketId; ByteBuf buf = Unpooled.buffer();
} ProtocolUtils.writeString(buf, address);
ProtocolUtils.writeString(buf, profile.getName());
public void setForwardingPacketId(int forwardingPacketId) { ProtocolUtils.writeUuid(buf, profile.idAsUuid());
this.forwardingPacketId = forwardingPacketId; 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;
} }
} }

Datei anzeigen

@ -2,28 +2,21 @@ package com.velocitypowered.proxy.connection.backend;
import com.velocitypowered.proxy.config.IPForwardingMode; import com.velocitypowered.proxy.config.IPForwardingMode;
import com.velocitypowered.proxy.connection.MinecraftConnectionAssociation; 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.ProtocolConstants;
import com.velocitypowered.proxy.protocol.ProtocolUtils;
import com.velocitypowered.proxy.protocol.netty.MinecraftDecoder; import com.velocitypowered.proxy.protocol.netty.MinecraftDecoder;
import com.velocitypowered.proxy.protocol.netty.MinecraftEncoder; import com.velocitypowered.proxy.protocol.netty.MinecraftEncoder;
import com.velocitypowered.proxy.protocol.netty.MinecraftVarintFrameDecoder; import com.velocitypowered.proxy.protocol.netty.MinecraftVarintFrameDecoder;
import com.velocitypowered.proxy.protocol.netty.MinecraftVarintLengthEncoder; import com.velocitypowered.proxy.protocol.netty.MinecraftVarintLengthEncoder;
import com.velocitypowered.proxy.protocol.packets.Handshake; 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.protocol.packets.ServerLogin;
import com.velocitypowered.proxy.connection.MinecraftConnection; import com.velocitypowered.proxy.connection.MinecraftConnection;
import com.velocitypowered.proxy.protocol.StateRegistry; import com.velocitypowered.proxy.protocol.StateRegistry;
import com.velocitypowered.proxy.data.ServerInfo; import com.velocitypowered.proxy.data.ServerInfo;
import com.velocitypowered.proxy.VelocityServer; import com.velocitypowered.proxy.VelocityServer;
import com.velocitypowered.proxy.connection.client.ConnectedPlayer; import com.velocitypowered.proxy.connection.client.ConnectedPlayer;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*; import io.netty.channel.*;
import io.netty.handler.timeout.ReadTimeoutHandler; import io.netty.handler.timeout.ReadTimeoutHandler;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import static com.velocitypowered.network.Connections.FRAME_DECODER; import static com.velocitypowered.network.Connections.FRAME_DECODER;
@ -38,7 +31,7 @@ public class ServerConnection implements MinecraftConnectionAssociation {
private final ServerInfo serverInfo; private final ServerInfo serverInfo;
private final ConnectedPlayer proxyPlayer; private final ConnectedPlayer proxyPlayer;
private final VelocityServer server; private final VelocityServer server;
private MinecraftConnection channel; private MinecraftConnection minecraftConnection;
public ServerConnection(ServerInfo target, ConnectedPlayer proxyPlayer, VelocityServer server) { public ServerConnection(ServerInfo target, ConnectedPlayer proxyPlayer, VelocityServer server) {
this.serverInfo = target; this.serverInfo = target;
@ -60,7 +53,6 @@ public class ServerConnection implements MinecraftConnectionAssociation {
MinecraftConnection connection = new MinecraftConnection(ch); MinecraftConnection connection = new MinecraftConnection(ch);
connection.setState(StateRegistry.HANDSHAKE); connection.setState(StateRegistry.HANDSHAKE);
connection.setSessionHandler(new LoginSessionHandler(ServerConnection.this));
connection.setAssociation(ServerConnection.this); connection.setAssociation(ServerConnection.this);
ch.pipeline().addLast(HANDLER, connection); ch.pipeline().addLast(HANDLER, connection);
} }
@ -70,9 +62,10 @@ public class ServerConnection implements MinecraftConnectionAssociation {
@Override @Override
public void operationComplete(ChannelFuture future) throws Exception { public void operationComplete(ChannelFuture future) throws Exception {
if (future.isSuccess()) { if (future.isSuccess()) {
channel = future.channel().pipeline().get(MinecraftConnection.class); minecraftConnection = future.channel().pipeline().get(MinecraftConnection.class);
// Kick off the connection process // Kick off the connection process
minecraftConnection.setSessionHandler(new LoginSessionHandler(ServerConnection.this));
startHandshake(); startHandshake();
} else { } else {
proxyPlayer.handleConnectionException(serverInfo, future.cause()); proxyPlayer.handleConnectionException(serverInfo, future.cause());
@ -102,43 +95,27 @@ public class ServerConnection implements MinecraftConnectionAssociation {
handshake.setServerAddress(serverInfo.getAddress().getHostString()); handshake.setServerAddress(serverInfo.getAddress().getHostString());
} }
handshake.setPort(serverInfo.getAddress().getPort()); handshake.setPort(serverInfo.getAddress().getPort());
channel.write(handshake); minecraftConnection.write(handshake);
int protocolVersion = proxyPlayer.getConnection().getProtocolVersion(); int protocolVersion = proxyPlayer.getConnection().getProtocolVersion();
channel.setProtocolVersion(protocolVersion); minecraftConnection.setProtocolVersion(protocolVersion);
channel.setState(StateRegistry.LOGIN); minecraftConnection.setState(StateRegistry.LOGIN);
// 1.13 stuff // Send the server login packet for <=1.12.2 and for 1.13+ servers not using "modern" forwarding.
if (protocolVersion >= ProtocolConstants.MINECRAFT_1_13) { if (protocolVersion <= ProtocolConstants.MINECRAFT_1_12_2 ||
if (VelocityServer.getServer().getConfiguration().getIpForwardingMode() == IPForwardingMode.MODERN) { VelocityServer.getServer().getConfiguration().getIpForwardingMode() != IPForwardingMode.MODERN) {
// Velocity's IP forwarding includes the player's IP address and their game profile. ServerLogin login = new ServerLogin();
GameProfile profile = proxyPlayer.getProfile(); login.setUsername(proxyPlayer.getUsername());
ByteBuf buf = createForwardingData(proxyPlayer.getRemoteAddress().getHostString(), profile); minecraftConnection.write(login);
// 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);
}
} }
// Login
ServerLogin login = new ServerLogin();
login.setUsername(proxyPlayer.getUsername());
channel.write(login);
} }
public ConnectedPlayer getProxyPlayer() { public ConnectedPlayer getProxyPlayer() {
return proxyPlayer; return proxyPlayer;
} }
public MinecraftConnection getChannel() { public MinecraftConnection getMinecraftConnection() {
return channel; return minecraftConnection;
} }
public ServerInfo getServerInfo() { public ServerInfo getServerInfo() {
@ -146,32 +123,12 @@ public class ServerConnection implements MinecraftConnectionAssociation {
} }
public void disconnect() { public void disconnect() {
channel.close(); minecraftConnection.close();
channel = null; minecraftConnection = null;
} }
@Override @Override
public String toString() { public String toString() {
return "[server connection] " + proxyPlayer.getProfile().getName() + " -> " + serverInfo.getName(); 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;
}
} }

Datei anzeigen

@ -93,18 +93,18 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
} }
// If we don't want to handle this packet, just forward it on. // If we don't want to handle this packet, just forward it on.
player.getConnectedServer().getChannel().write(packet); player.getConnectedServer().getMinecraftConnection().write(packet);
} }
@Override @Override
public void handleUnknown(ByteBuf buf) { public void handleUnknown(ByteBuf buf) {
ByteBuf remapped = idRemapper.remap(buf, ProtocolConstants.Direction.SERVERBOUND); ByteBuf remapped = idRemapper.remap(buf, ProtocolConstants.Direction.SERVERBOUND);
player.getConnectedServer().getChannel().write(remapped); player.getConnectedServer().getMinecraftConnection().write(remapped);
} }
@Override @Override
public void disconnected() { public void disconnected() {
player.getConnectedServer().disconnect(); player.teardown();
if (pingTask != null && !pingTask.isCancelled()) { if (pingTask != null && !pingTask.isCancelled()) {
pingTask.cancel(false); 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 // Resend client settings packet to remote server if we have it, this preserves client settings across
// transitions. // transitions.
if (player.getClientSettings() != null) { if (player.getClientSettings() != null) {
player.getConnectedServer().getChannel().delayedWrite(player.getClientSettings()); player.getConnectedServer().getMinecraftConnection().delayedWrite(player.getClientSettings());
} }
// Remove old boss bars. // Remove old boss bars.
@ -169,19 +169,19 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
if (!clientPluginMsgChannels.isEmpty()) { if (!clientPluginMsgChannels.isEmpty()) {
String channel = player.getConnection().getProtocolVersion() >= ProtocolConstants.MINECRAFT_1_13 ? String channel = player.getConnection().getProtocolVersion() >= ProtocolConstants.MINECRAFT_1_13 ?
"minecraft:register" : "REGISTER"; "minecraft:register" : "REGISTER";
player.getConnectedServer().getChannel().delayedWrite( player.getConnectedServer().getMinecraftConnection().delayedWrite(
PluginMessageUtil.constructChannelsPacket(channel, clientPluginMsgChannels)); PluginMessageUtil.constructChannelsPacket(channel, clientPluginMsgChannels));
} }
// Tell the server the client's brand // Tell the server the client's brand
if (brandMessage != null) { if (brandMessage != null) {
brandMessage.getData().retain(); brandMessage.getData().retain();
player.getConnectedServer().getChannel().delayedWrite(brandMessage); player.getConnectedServer().getMinecraftConnection().delayedWrite(brandMessage);
} }
// Flush everything // Flush everything
player.getConnection().flush(); player.getConnection().flush();
player.getConnectedServer().getChannel().flush(); player.getConnectedServer().getMinecraftConnection().flush();
} }
public void setCurrentDimension(int currentDimension) { public void setCurrentDimension(int currentDimension) {
@ -213,7 +213,7 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
if (actuallyRegistered.size() > 0) { if (actuallyRegistered.size() > 0) {
logger.info("Rewritten register packet: {}", actuallyRegistered); logger.info("Rewritten register packet: {}", actuallyRegistered);
PluginMessage newRegisterPacket = PluginMessageUtil.constructChannelsPacket(packet.getChannel(), actuallyRegistered); PluginMessage newRegisterPacket = PluginMessageUtil.constructChannelsPacket(packet.getChannel(), actuallyRegistered);
player.getConnectedServer().getChannel().write(newRegisterPacket); player.getConnectedServer().getMinecraftConnection().write(newRegisterPacket);
} }
return; return;
@ -242,7 +242,7 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
packet.getData().retain(); packet.getData().retain();
} }
player.getConnectedServer().getChannel().write(packet); player.getConnectedServer().getMinecraftConnection().write(packet);
} finally { } finally {
ReferenceCountUtil.release(original.getData()); ReferenceCountUtil.release(original.getData());
} }

Datei anzeigen

@ -21,6 +21,7 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.UUID; import java.util.UUID;
@ -35,6 +36,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation {
private int tryIndex = 0; private int tryIndex = 0;
private ServerConnection connectedServer; private ServerConnection connectedServer;
private ClientSettings clientSettings; private ClientSettings clientSettings;
private ServerConnection connectionInFlight;
public ConnectedPlayer(GameProfile profile, MinecraftConnection connection) { public ConnectedPlayer(GameProfile profile, MinecraftConnection connection) {
this.profile = profile; this.profile = profile;
@ -101,7 +103,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation {
handleConnectionException(info, disconnectReason); handleConnectionException(info, disconnectReason);
} }
private void handleConnectionException(ServerInfo info, Component disconnectReason) { public void handleConnectionException(ServerInfo info, Component disconnectReason) {
if (connectedServer == null || connectedServer.getServerInfo().equals(info)) { if (connectedServer == null || connectedServer.getServerInfo().equals(info)) {
// The player isn't yet connected to a server or they are already connected to the server // The player isn't yet connected to a server or they are already connected to the server
// they're disconnected from. // they're disconnected from.
@ -124,7 +126,9 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation {
public void connect(ServerInfo info) { public void connect(ServerInfo info) {
Preconditions.checkNotNull(info, "info"); Preconditions.checkNotNull(info, "info");
Preconditions.checkState(connectionInFlight == null, "A connection is already active!");
ServerConnection connection = new ServerConnection(info, this, VelocityServer.getServer()); ServerConnection connection = new ServerConnection(info, this, VelocityServer.getServer());
connectionInFlight = connection;
connection.connect(); connection.connect();
} }
@ -139,6 +143,15 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation {
connection.closeWith(Disconnect.create(reason)); connection.closeWith(Disconnect.create(reason));
} }
public void teardown() {
if (connectionInFlight != null) {
connectionInFlight.disconnect();
}
if (connectedServer != null) {
connectedServer.disconnect();
}
}
@Override @Override
public String toString() { public String toString() {
return "[connected player] " + getProfile().getName() + " (" + getRemoteAddress() + ")"; return "[connected player] " + getProfile().getName() + " (" + getRemoteAddress() + ")";

Datei anzeigen

@ -18,6 +18,6 @@ public class InitialConnectSessionHandler implements MinecraftSessionHandler {
@Override @Override
public void disconnected() { public void disconnected() {
// the user cancelled the login process // the user cancelled the login process
player.getConnectedServer().disconnect(); player.teardown();
} }
} }

Datei anzeigen

@ -4,6 +4,7 @@ import com.google.common.base.Preconditions;
import com.velocitypowered.proxy.connection.VelocityConstants; import com.velocitypowered.proxy.connection.VelocityConstants;
import com.velocitypowered.proxy.data.GameProfile; import com.velocitypowered.proxy.data.GameProfile;
import com.velocitypowered.proxy.protocol.MinecraftPacket; import com.velocitypowered.proxy.protocol.MinecraftPacket;
import com.velocitypowered.proxy.protocol.ProtocolConstants;
import com.velocitypowered.proxy.protocol.StateRegistry; import com.velocitypowered.proxy.protocol.StateRegistry;
import com.velocitypowered.proxy.protocol.packets.*; import com.velocitypowered.proxy.protocol.packets.*;
import com.velocitypowered.proxy.connection.MinecraftConnection; import com.velocitypowered.proxy.connection.MinecraftConnection;
@ -35,27 +36,33 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
private final MinecraftConnection inbound; private final MinecraftConnection inbound;
private ServerLogin login; private ServerLogin login;
private byte[] verify; private byte[] verify;
private int playerInfoId;
public LoginSessionHandler(MinecraftConnection inbound) { public LoginSessionHandler(MinecraftConnection inbound) {
this.inbound = Preconditions.checkNotNull(inbound, "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 @Override
public void handle(MinecraftPacket packet) throws Exception { public void handle(MinecraftPacket packet) throws Exception {
if (packet instanceof LoginPluginMessage) { if (packet instanceof LoginPluginResponse) {
LoginPluginMessage lpm = (LoginPluginMessage) packet; LoginPluginResponse lpr = (LoginPluginResponse) packet;
if (lpm.getChannel().equals(VelocityConstants.VELOCITY_IP_FORWARDING_CHANNEL)) { if (lpr.getId() == playerInfoId && lpr.isSuccess()) {
// Uh oh, someone's trying to run Velocity behind Velocity. We don't want that happening. // Uh oh, someone's trying to run Velocity behind Velocity. We don't want that happening.
inbound.closeWith(Disconnect.create( inbound.closeWith(Disconnect.create(
TextComponent.of("Running Velocity behind Velocity isn't supported.", TextColor.RED) 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) { } else if (packet instanceof ServerLogin) {
this.login = (ServerLogin) packet; this.login = (ServerLogin) packet;

Datei anzeigen

@ -108,7 +108,7 @@ public enum StateRegistry {
genericMappings(0x00)); genericMappings(0x00));
SERVERBOUND.register(EncryptionResponse.class, EncryptionResponse::new, SERVERBOUND.register(EncryptionResponse.class, EncryptionResponse::new,
genericMappings(0x01)); genericMappings(0x01));
SERVERBOUND.register(LoginPluginMessage.class, LoginPluginMessage::new, SERVERBOUND.register(LoginPluginResponse.class, LoginPluginResponse::new,
map(0x02, MINECRAFT_1_13)); map(0x02, MINECRAFT_1_13));
CLIENTBOUND.register(Disconnect.class, Disconnect::new, CLIENTBOUND.register(Disconnect.class, Disconnect::new,
@ -119,7 +119,7 @@ public enum StateRegistry {
genericMappings(0x02)); genericMappings(0x02));
CLIENTBOUND.register(SetCompression.class, SetCompression::new, CLIENTBOUND.register(SetCompression.class, SetCompression::new,
genericMappings(0x03)); genericMappings(0x03));
CLIENTBOUND.register(LoginPluginResponse.class, LoginPluginResponse::new, CLIENTBOUND.register(LoginPluginMessage.class, LoginPluginMessage::new,
map(0x04, MINECRAFT_1_13)); map(0x04, MINECRAFT_1_13));
} }
}; };