geforkt von Mirrors/Velocity
Consistently display disconnects.
Dieser Commit ist enthalten in:
Ursprung
256978fc15
Commit
10c440af83
@ -24,6 +24,7 @@ import com.velocitypowered.proxy.protocol.netty.MinecraftCompressDecoder;
|
||||
import com.velocitypowered.proxy.protocol.netty.MinecraftCompressEncoder;
|
||||
import com.velocitypowered.proxy.protocol.netty.MinecraftDecoder;
|
||||
import com.velocitypowered.proxy.protocol.netty.MinecraftEncoder;
|
||||
import com.velocitypowered.proxy.protocol.packet.Disconnect;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelFutureListener;
|
||||
@ -58,6 +59,7 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter {
|
||||
private @Nullable MinecraftConnectionAssociation association;
|
||||
private final VelocityServer server;
|
||||
private ConnectionType connectionType = ConnectionTypes.UNDETERMINED;
|
||||
private boolean knownDisconnect = false;
|
||||
|
||||
/**
|
||||
* Initializes a new {@link MinecraftConnection} instance.
|
||||
@ -88,7 +90,7 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter {
|
||||
sessionHandler.disconnected();
|
||||
}
|
||||
|
||||
if (association != null) {
|
||||
if (association != null && !knownDisconnect) {
|
||||
logger.info("{} has disconnected", association);
|
||||
}
|
||||
}
|
||||
@ -191,6 +193,7 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter {
|
||||
*/
|
||||
public void closeWith(Object msg) {
|
||||
if (channel.isActive()) {
|
||||
knownDisconnect = true;
|
||||
channel.writeAndFlush(msg).addListener(ChannelFutureListener.CLOSE);
|
||||
}
|
||||
}
|
||||
|
@ -235,6 +235,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
|
||||
|
||||
@Override
|
||||
public void disconnect(Component reason) {
|
||||
logger.info("{} has disconnected: {}", this, ComponentSerializers.LEGACY.serialize(reason));
|
||||
connection.closeWith(Disconnect.create(reason));
|
||||
}
|
||||
|
||||
@ -351,7 +352,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
|
||||
if (nextServer.isPresent()) {
|
||||
createConnectionRequest(nextServer.get()).fireAndForget();
|
||||
} else {
|
||||
connection.closeWith(Disconnect.create(friendlyReason));
|
||||
disconnect(friendlyReason);
|
||||
}
|
||||
} else {
|
||||
KickedFromServerEvent originalEvent = new KickedFromServerEvent(this, rs, kickReason,
|
||||
@ -360,7 +361,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
|
||||
.thenAcceptAsync(event -> {
|
||||
if (event.getResult() instanceof DisconnectPlayer) {
|
||||
DisconnectPlayer res = (DisconnectPlayer) event.getResult();
|
||||
connection.closeWith(Disconnect.create(res.getReason()));
|
||||
disconnect(res.getReason());
|
||||
} else if (event.getResult() instanceof RedirectPlayer) {
|
||||
RedirectPlayer res = (RedirectPlayer) event.getResult();
|
||||
createConnectionRequest(res.getServer()).fireAndForget();
|
||||
@ -369,11 +370,11 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
|
||||
if (event.kickedDuringServerConnect()) {
|
||||
sendMessage(res.getMessage());
|
||||
} else {
|
||||
connection.closeWith(Disconnect.create(res.getMessage()));
|
||||
disconnect(res.getMessage());
|
||||
}
|
||||
} else {
|
||||
// In case someone gets creative, assume we want to disconnect the player.
|
||||
connection.closeWith(Disconnect.create(friendlyReason));
|
||||
disconnect(friendlyReason);
|
||||
}
|
||||
}, connection.eventLoop());
|
||||
}
|
||||
|
@ -4,9 +4,9 @@ import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.velocitypowered.api.event.connection.ConnectionHandshakeEvent;
|
||||
import com.velocitypowered.api.event.proxy.ProxyPingEvent;
|
||||
import com.velocitypowered.api.network.ProtocolVersion;
|
||||
import com.velocitypowered.api.proxy.InboundConnection;
|
||||
import com.velocitypowered.api.proxy.server.ServerPing;
|
||||
import com.velocitypowered.api.network.ProtocolVersion;
|
||||
import com.velocitypowered.proxy.VelocityServer;
|
||||
import com.velocitypowered.proxy.config.PlayerInfoForwarding;
|
||||
import com.velocitypowered.proxy.config.VelocityConfiguration;
|
||||
@ -75,6 +75,7 @@ public class HandshakeSessionHandler implements MinecraftSessionHandler {
|
||||
public boolean handle(Handshake handshake) {
|
||||
InitialInboundConnection ic = new InitialInboundConnection(connection,
|
||||
cleanVhost(handshake.getServerAddress()), handshake);
|
||||
connection.setAssociation(ic);
|
||||
switch (handshake.getNextStatus()) {
|
||||
case StateRegistry.STATUS_ID:
|
||||
connection.setState(StateRegistry.STATUS);
|
||||
|
@ -3,11 +3,19 @@ package com.velocitypowered.proxy.connection.client;
|
||||
import com.velocitypowered.api.proxy.InboundConnection;
|
||||
import com.velocitypowered.api.network.ProtocolVersion;
|
||||
import com.velocitypowered.proxy.connection.MinecraftConnection;
|
||||
import com.velocitypowered.proxy.connection.MinecraftConnectionAssociation;
|
||||
import com.velocitypowered.proxy.protocol.packet.Disconnect;
|
||||
import com.velocitypowered.proxy.protocol.packet.Handshake;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.Optional;
|
||||
import net.kyori.text.Component;
|
||||
import net.kyori.text.serializer.ComponentSerializers;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
class InitialInboundConnection implements InboundConnection {
|
||||
class InitialInboundConnection implements InboundConnection, MinecraftConnectionAssociation {
|
||||
|
||||
private static final Logger logger = LogManager.getLogger(InitialInboundConnection.class);
|
||||
|
||||
private final MinecraftConnection connection;
|
||||
private final String cleanedAddress;
|
||||
@ -39,4 +47,14 @@ class InitialInboundConnection implements InboundConnection {
|
||||
public ProtocolVersion getProtocolVersion() {
|
||||
return connection.getProtocolVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[initial connection] " + connection.getRemoteAddress().toString();
|
||||
}
|
||||
|
||||
public void disconnect(Component reason) {
|
||||
logger.info("{} has disconnected: {}", this, ComponentSerializers.LEGACY.serialize(reason));
|
||||
connection.closeWith(Disconnect.create(reason));
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +31,6 @@ import com.velocitypowered.proxy.protocol.packet.LoginPluginResponse;
|
||||
import com.velocitypowered.proxy.protocol.packet.ServerLogin;
|
||||
import com.velocitypowered.proxy.protocol.packet.ServerLoginSuccess;
|
||||
import com.velocitypowered.proxy.protocol.packet.SetCompression;
|
||||
import com.velocitypowered.proxy.util.EncryptionUtils;
|
||||
import com.velocitypowered.proxy.util.VelocityMessages;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufUtil;
|
||||
@ -57,26 +56,26 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
|
||||
"https://sessionserver.mojang.com/session/minecraft/hasJoined?username=%s&serverId=%s&ip=%s";
|
||||
|
||||
private final VelocityServer server;
|
||||
private final MinecraftConnection inbound;
|
||||
private final InboundConnection apiInbound;
|
||||
private final MinecraftConnection mcConnection;
|
||||
private final InitialInboundConnection inbound;
|
||||
private @MonotonicNonNull ServerLogin login;
|
||||
private byte[] verify = EMPTY_BYTE_ARRAY;
|
||||
private int playerInfoId;
|
||||
private @MonotonicNonNull ConnectedPlayer connectedPlayer;
|
||||
|
||||
LoginSessionHandler(VelocityServer server, MinecraftConnection inbound,
|
||||
InboundConnection apiInbound) {
|
||||
LoginSessionHandler(VelocityServer server, MinecraftConnection mcConnection,
|
||||
InitialInboundConnection inbound) {
|
||||
this.server = Preconditions.checkNotNull(server, "server");
|
||||
this.mcConnection = Preconditions.checkNotNull(mcConnection, "mcConnection");
|
||||
this.inbound = Preconditions.checkNotNull(inbound, "inbound");
|
||||
this.apiInbound = Preconditions.checkNotNull(apiInbound, "apiInbound");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(ServerLogin packet) {
|
||||
this.login = packet;
|
||||
if (inbound.getProtocolVersion().compareTo(MINECRAFT_1_13) >= 0) {
|
||||
if (mcConnection.getProtocolVersion().compareTo(MINECRAFT_1_13) >= 0) {
|
||||
playerInfoId = ThreadLocalRandom.current().nextInt();
|
||||
inbound.write(new LoginPluginMessage(playerInfoId, VELOCITY_IP_FORWARDING_CHANNEL,
|
||||
mcConnection.write(new LoginPluginMessage(playerInfoId, VELOCITY_IP_FORWARDING_CHANNEL,
|
||||
Unpooled.EMPTY_BUFFER));
|
||||
} else {
|
||||
beginPreLogin();
|
||||
@ -89,7 +88,7 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
|
||||
if (packet.getId() == playerInfoId) {
|
||||
if (packet.isSuccess()) {
|
||||
// Uh oh, someone's trying to run Velocity behind Velocity. We don't want that happening.
|
||||
inbound.closeWith(Disconnect.create(VelocityMessages.NO_PROXY_BEHIND_PROXY));
|
||||
inbound.disconnect(VelocityMessages.NO_PROXY_BEHIND_PROXY);
|
||||
} else {
|
||||
// Proceed with the regular login process.
|
||||
beginPreLogin();
|
||||
@ -119,14 +118,14 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
|
||||
byte[] decryptedSharedSecret = decryptRsa(serverKeyPair, packet.getSharedSecret());
|
||||
String serverId = generateServerId(decryptedSharedSecret, serverKeyPair.getPublic());
|
||||
|
||||
String playerIp = ((InetSocketAddress) inbound.getRemoteAddress()).getHostString();
|
||||
String playerIp = ((InetSocketAddress) mcConnection.getRemoteAddress()).getHostString();
|
||||
String url = String.format(MOJANG_HASJOINED_URL,
|
||||
UrlEscapers.urlFormParameterEscaper().escape(login.getUsername()), serverId,
|
||||
UrlEscapers.urlFormParameterEscaper().escape(playerIp));
|
||||
server.getHttpClient()
|
||||
.get(new URL(url))
|
||||
.thenAcceptAsync(profileResponse -> {
|
||||
if (inbound.isClosed()) {
|
||||
if (mcConnection.isClosed()) {
|
||||
// The player disconnected after we authenticated them.
|
||||
return;
|
||||
}
|
||||
@ -134,7 +133,7 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
|
||||
// Go ahead and enable encryption. Once the client sends EncryptionResponse, encryption
|
||||
// is enabled.
|
||||
try {
|
||||
inbound.enableEncryption(decryptedSharedSecret);
|
||||
mcConnection.enableEncryption(decryptedSharedSecret);
|
||||
} catch (GeneralSecurityException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
@ -144,25 +143,23 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
|
||||
initializePlayer(GSON.fromJson(profileResponse.getBody(), GameProfile.class), true);
|
||||
} else if (profileResponse.getCode() == 204) {
|
||||
// Apparently an offline-mode user logged onto this online-mode proxy.
|
||||
logger.warn("An offline-mode client ({} from {}) tried to connect!",
|
||||
login.getUsername(), playerIp);
|
||||
inbound.closeWith(Disconnect.create(VelocityMessages.ONLINE_MODE_ONLY));
|
||||
inbound.disconnect(VelocityMessages.ONLINE_MODE_ONLY);
|
||||
} else {
|
||||
// Something else went wrong
|
||||
logger.error(
|
||||
"Got an unexpected error code {} whilst contacting Mojang to log in {} ({})",
|
||||
profileResponse.getCode(), login.getUsername(), playerIp);
|
||||
inbound.close();
|
||||
mcConnection.close();
|
||||
}
|
||||
}, inbound.eventLoop())
|
||||
}, mcConnection.eventLoop())
|
||||
.exceptionally(exception -> {
|
||||
logger.error("Unable to enable encryption", exception);
|
||||
inbound.close();
|
||||
mcConnection.close();
|
||||
return null;
|
||||
});
|
||||
} catch (GeneralSecurityException e) {
|
||||
logger.error("Unable to enable encryption", e);
|
||||
inbound.close();
|
||||
mcConnection.close();
|
||||
} catch (MalformedURLException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
@ -174,10 +171,10 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
|
||||
if (login == null) {
|
||||
throw new IllegalStateException("No ServerLogin packet received yet.");
|
||||
}
|
||||
PreLoginEvent event = new PreLoginEvent(apiInbound, login.getUsername());
|
||||
PreLoginEvent event = new PreLoginEvent(inbound, login.getUsername());
|
||||
server.getEventManager().fire(event)
|
||||
.thenRunAsync(() -> {
|
||||
if (inbound.isClosed()) {
|
||||
if (mcConnection.isClosed()) {
|
||||
// The player was disconnected
|
||||
return;
|
||||
}
|
||||
@ -185,7 +182,7 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
|
||||
Optional<Component> disconnectReason = result.getReason();
|
||||
if (disconnectReason.isPresent()) {
|
||||
// The component is guaranteed to be provided if the connection was denied.
|
||||
inbound.closeWith(Disconnect.create(disconnectReason.get()));
|
||||
mcConnection.closeWith(Disconnect.create(disconnectReason.get()));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -194,11 +191,11 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
|
||||
// Request encryption.
|
||||
EncryptionRequest request = generateEncryptionRequest();
|
||||
this.verify = Arrays.copyOf(request.getVerifyToken(), 4);
|
||||
inbound.write(request);
|
||||
mcConnection.write(request);
|
||||
} else {
|
||||
initializePlayer(GameProfile.forOfflinePlayer(login.getUsername()), false);
|
||||
}
|
||||
}, inbound.eventLoop());
|
||||
}, mcConnection.eventLoop());
|
||||
}
|
||||
|
||||
private EncryptionRequest generateEncryptionRequest() {
|
||||
@ -213,15 +210,16 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
|
||||
|
||||
private void initializePlayer(GameProfile profile, boolean onlineMode) {
|
||||
// Some connection types may need to alter the game profile.
|
||||
profile = inbound.getType().addGameProfileTokensIfRequired(profile,
|
||||
profile = mcConnection.getType().addGameProfileTokensIfRequired(profile,
|
||||
server.getConfiguration().getPlayerInfoForwardingMode());
|
||||
GameProfileRequestEvent profileRequestEvent = new GameProfileRequestEvent(apiInbound, profile,
|
||||
GameProfileRequestEvent profileRequestEvent = new GameProfileRequestEvent(inbound, profile,
|
||||
onlineMode);
|
||||
|
||||
server.getEventManager().fire(profileRequestEvent).thenCompose(profileEvent -> {
|
||||
// Initiate a regular connection and move over to it.
|
||||
ConnectedPlayer player = new ConnectedPlayer(server, profileEvent.getGameProfile(), inbound,
|
||||
apiInbound.getVirtualHost().orElse(null));
|
||||
ConnectedPlayer player = new ConnectedPlayer(server, profileEvent.getGameProfile(),
|
||||
mcConnection,
|
||||
inbound.getVirtualHost().orElse(null));
|
||||
this.connectedPlayer = player;
|
||||
|
||||
if (!server.registerConnection(player)) {
|
||||
@ -229,6 +227,8 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
|
||||
logger.info("{} has connected", player);
|
||||
|
||||
return server.getEventManager()
|
||||
.fire(new PermissionsSetupEvent(player, ConnectedPlayer.DEFAULT_PERMISSIONS))
|
||||
.thenCompose(event -> {
|
||||
@ -239,7 +239,7 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
|
||||
})
|
||||
// then complete the connection
|
||||
.thenAcceptAsync(event -> {
|
||||
if (inbound.isClosed()) {
|
||||
if (mcConnection.isClosed()) {
|
||||
// The player was disconnected
|
||||
return;
|
||||
}
|
||||
@ -250,7 +250,7 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
|
||||
} else {
|
||||
finishLogin(player);
|
||||
}
|
||||
}, inbound.eventLoop());
|
||||
}, mcConnection.eventLoop());
|
||||
});
|
||||
|
||||
}
|
||||
@ -264,27 +264,26 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
|
||||
|
||||
int threshold = server.getConfiguration().getCompressionThreshold();
|
||||
if (threshold >= 0) {
|
||||
inbound.write(new SetCompression(threshold));
|
||||
inbound.setCompressionThreshold(threshold);
|
||||
mcConnection.write(new SetCompression(threshold));
|
||||
mcConnection.setCompressionThreshold(threshold);
|
||||
}
|
||||
|
||||
ServerLoginSuccess success = new ServerLoginSuccess();
|
||||
success.setUsername(player.getUsername());
|
||||
success.setUuid(player.getUniqueId());
|
||||
inbound.write(success);
|
||||
mcConnection.write(success);
|
||||
|
||||
inbound.setAssociation(player);
|
||||
inbound.setState(StateRegistry.PLAY);
|
||||
mcConnection.setAssociation(player);
|
||||
mcConnection.setState(StateRegistry.PLAY);
|
||||
|
||||
logger.info("{} has connected", player);
|
||||
inbound.setSessionHandler(new InitialConnectSessionHandler(player));
|
||||
mcConnection.setSessionHandler(new InitialConnectSessionHandler(player));
|
||||
server.getEventManager().fire(new PostLoginEvent(player))
|
||||
.thenRun(() -> player.createConnectionRequest(toTry.get()).fireAndForget());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleUnknown(ByteBuf buf) {
|
||||
throw new IllegalStateException("Unknown data " + ByteBufUtil.hexDump(buf));
|
||||
mcConnection.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -14,8 +14,6 @@ public class VelocityMessages {
|
||||
.of("No available servers", TextColor.RED);
|
||||
public static final Component ALREADY_CONNECTED = TextComponent
|
||||
.of("You are already connected to this proxy!", TextColor.RED);
|
||||
public static final Component INVALID_USERNAME = TextComponent
|
||||
.of("Trying to login with invalid username", TextColor.RED);
|
||||
|
||||
private VelocityMessages() {
|
||||
throw new AssertionError();
|
||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren