From 9269751ed16fe0df17045982893fef2f464421e9 Mon Sep 17 00:00:00 2001 From: Nanit Date: Mon, 7 Feb 2022 18:10:40 +0200 Subject: [PATCH] Reformatted packet handling. Moved packet snapshot in separated class --- .../connection/ClientChannelInitializer.java | 3 +- .../limbo/connection/ClientConnection.java | 323 +++--------------- .../nanit/limbo/connection/PacketHandler.java | 129 +++++++ .../limbo/connection/PacketSnapshots.java | 175 ++++++++++ .../java/ru/nanit/limbo/protocol/Packet.java | 6 + .../protocol/packets/PacketHandshake.java | 9 + .../login/PacketLoginPluginResponse.java | 7 + .../packets/login/PacketLoginStart.java | 7 + .../packets/status/PacketStatusPing.java | 7 + .../packets/status/PacketStatusRequest.java | 7 + .../ru/nanit/limbo/server/LimboServer.java | 10 +- 11 files changed, 409 insertions(+), 274 deletions(-) create mode 100644 src/main/java/ru/nanit/limbo/connection/PacketHandler.java create mode 100644 src/main/java/ru/nanit/limbo/connection/PacketSnapshots.java diff --git a/src/main/java/ru/nanit/limbo/connection/ClientChannelInitializer.java b/src/main/java/ru/nanit/limbo/connection/ClientChannelInitializer.java index f564760..c394606 100644 --- a/src/main/java/ru/nanit/limbo/connection/ClientChannelInitializer.java +++ b/src/main/java/ru/nanit/limbo/connection/ClientChannelInitializer.java @@ -43,6 +43,7 @@ public class ClientChannelInitializer extends ChannelInitializer { PacketDecoder decoder = new PacketDecoder(); PacketEncoder encoder = new PacketEncoder(); + ClientConnection connection = new ClientConnection(channel, server, decoder, encoder); pipeline.addLast("timeout", new ReadTimeoutHandler(server.getConfig().getReadTimeout(), TimeUnit.MILLISECONDS)); @@ -50,7 +51,7 @@ public class ClientChannelInitializer extends ChannelInitializer { pipeline.addLast("frame_encoder", new VarIntLengthEncoder()); pipeline.addLast("decoder", decoder); pipeline.addLast("encoder", encoder); - pipeline.addLast("handler", new ClientConnection(channel, server, decoder, encoder)); + pipeline.addLast("handler", connection); } } diff --git a/src/main/java/ru/nanit/limbo/connection/ClientConnection.java b/src/main/java/ru/nanit/limbo/connection/ClientConnection.java index f36fe6b..4d4324b 100644 --- a/src/main/java/ru/nanit/limbo/connection/ClientConnection.java +++ b/src/main/java/ru/nanit/limbo/connection/ClientConnection.java @@ -21,26 +21,20 @@ import com.grack.nanojson.JsonArray; import com.grack.nanojson.JsonObject; import com.grack.nanojson.JsonParser; import com.grack.nanojson.JsonParserException; -import io.netty.buffer.Unpooled; import io.netty.channel.Channel; import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; -import ru.nanit.limbo.LimboConstants; +import org.jetbrains.annotations.NotNull; import ru.nanit.limbo.connection.pipeline.PacketDecoder; import ru.nanit.limbo.connection.pipeline.PacketEncoder; import ru.nanit.limbo.protocol.ByteMessage; -import ru.nanit.limbo.protocol.PacketSnapshot; -import ru.nanit.limbo.protocol.packets.PacketHandshake; +import ru.nanit.limbo.protocol.Packet; import ru.nanit.limbo.protocol.packets.login.*; import ru.nanit.limbo.protocol.packets.play.*; -import ru.nanit.limbo.protocol.packets.status.PacketStatusPing; -import ru.nanit.limbo.protocol.packets.status.PacketStatusRequest; -import ru.nanit.limbo.protocol.packets.status.PacketStatusResponse; import ru.nanit.limbo.protocol.registry.State; import ru.nanit.limbo.protocol.registry.Version; import ru.nanit.limbo.server.LimboServer; -import ru.nanit.limbo.server.data.Title; import ru.nanit.limbo.server.Logger; import ru.nanit.limbo.util.UuidUtil; @@ -50,31 +44,11 @@ import java.net.InetSocketAddress; import java.net.SocketAddress; import java.security.InvalidKeyException; import java.security.MessageDigest; -import java.util.Collections; import java.util.UUID; import java.util.concurrent.ThreadLocalRandom; public class ClientConnection extends ChannelInboundHandlerAdapter { - private static PacketSnapshot PACKET_LOGIN_SUCCESS; - private static PacketSnapshot PACKET_JOIN_GAME; - private static PacketSnapshot PACKET_PLUGIN_MESSAGE; - private static PacketSnapshot PACKET_PLAYER_ABILITIES; - private static PacketSnapshot PACKET_PLAYER_INFO; - private static PacketSnapshot PACKET_DECLARE_COMMANDS; - private static PacketSnapshot PACKET_PLAYER_POS; - private static PacketSnapshot PACKET_JOIN_MESSAGE; - private static PacketSnapshot PACKET_BOSS_BAR; - private static PacketSnapshot PACKET_HEADER_AND_FOOTER; - - private static PacketSnapshot PACKET_TITLE_TITLE; - private static PacketSnapshot PACKET_TITLE_SUBTITLE; - private static PacketSnapshot PACKET_TITLE_TIMES; - - private static PacketSnapshot PACKET_TITLE_LEGACY_TITLE; - private static PacketSnapshot PACKET_TITLE_LEGACY_SUBTITLE; - private static PacketSnapshot PACKET_TITLE_LEGACY_TIMES; - private final LimboServer server; private final Channel channel; private final GameProfile gameProfile; @@ -113,8 +87,12 @@ public class ClientConnection extends ChannelInboundHandlerAdapter { return clientVersion; } + public GameProfile getGameProfile() { + return gameProfile; + } + @Override - public void channelInactive(ChannelHandlerContext ctx) throws Exception { + public void channelInactive(@NotNull ChannelHandlerContext ctx) throws Exception { if (state.equals(State.PLAY)) { server.getConnections().removeConnection(this); } @@ -129,139 +107,52 @@ public class ClientConnection extends ChannelInboundHandlerAdapter { } @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) { + public void channelRead(@NotNull ChannelHandlerContext ctx, @NotNull Object msg) { handlePacket(msg); } public void handlePacket(Object packet) { - if (packet instanceof PacketHandshake) { - PacketHandshake handshake = (PacketHandshake) packet; - clientVersion = handshake.getVersion(); - - updateStateAndVersion(handshake.getNextState(), clientVersion); - - Logger.debug("Pinged from %s [%s]", address, clientVersion.toString()); - - if (server.getConfig().getInfoForwarding().isLegacy()) { - String[] split = handshake.getHost().split("\00"); - - if (split.length == 3 || split.length == 4) { - setAddress(split[1]); - gameProfile.setUuid(UuidUtil.fromString(split[2])); - } else { - disconnectLogin("You've enabled player info forwarding. You need to connect with proxy"); - } - } else if (server.getConfig().getInfoForwarding().isBungeeGuard()) { - if (!checkBungeeGuardHandshake(handshake.getHost())) { - disconnectLogin("Invalid BungeeGuard token or handshake format"); - } - } - return; - } - - if (packet instanceof PacketStatusRequest) { - sendPacket(new PacketStatusResponse(server)); - return; - } - - if (packet instanceof PacketStatusPing) { - sendPacketAndClose(packet); - return; - } - - if (packet instanceof PacketLoginStart) { - if (server.getConfig().getMaxPlayers() > 0 && - server.getConnections().getCount() >= server.getConfig().getMaxPlayers()) { - disconnectLogin("Too many players connected"); - return; - } - - if (!clientVersion.isSupported()) { - disconnectLogin("Unsupported client version"); - return; - } - - if (server.getConfig().getInfoForwarding().isModern()) { - velocityLoginMessageId = ThreadLocalRandom.current().nextInt(0, Integer.MAX_VALUE); - PacketLoginPluginRequest request = new PacketLoginPluginRequest(); - request.setMessageId(velocityLoginMessageId); - request.setChannel(LimboConstants.VELOCITY_INFO_CHANNEL); - request.setData(Unpooled.EMPTY_BUFFER); - sendPacket(request); - return; - } - - if (!server.getConfig().getInfoForwarding().isModern()) { - gameProfile.setUsername(((PacketLoginStart)packet).getUsername()); - gameProfile.setUuid(UuidUtil.getOfflineModeUuid(getUsername())); - } - - fireLoginSuccess(); - return; - } - - if (packet instanceof PacketLoginPluginResponse) { - PacketLoginPluginResponse response = (PacketLoginPluginResponse) packet; - - if (server.getConfig().getInfoForwarding().isModern() - && response.getMessageId() == velocityLoginMessageId) { - - if (!response.isSuccessful() || response.getData() == null) { - disconnectLogin("You need to connect with Velocity"); - return; - } - - if (!checkVelocityKeyIntegrity(response.getData())) { - disconnectLogin("Can't verify forwarded player info"); - return; - } - - // Order is important - setAddress(response.getData().readString()); - gameProfile.setUuid(response.getData().readUuid()); - gameProfile.setUsername(response.getData().readString()); - - fireLoginSuccess(); - } + if (packet instanceof Packet) { + ((Packet)packet).handle(this, server); } } - private void fireLoginSuccess() { + public void fireLoginSuccess() { if (server.getConfig().getInfoForwarding().isModern() && velocityLoginMessageId == -1) { disconnectLogin("You need to connect with Velocity"); return; } - writePacket(PACKET_LOGIN_SUCCESS); - setPlayState(); + writePacket(PacketSnapshots.PACKET_LOGIN_SUCCESS); + updateState(State.PLAY); server.getConnections().addConnection(this); - writePacket(PACKET_JOIN_GAME); - writePacket(PACKET_PLAYER_ABILITIES); - writePacket(PACKET_PLAYER_POS); + writePacket(PacketSnapshots.PACKET_JOIN_GAME); + writePacket(PacketSnapshots.PACKET_PLAYER_ABILITIES); + writePacket(PacketSnapshots.PACKET_PLAYER_POS); if (server.getConfig().isUsePlayerList() || clientVersion.equals(Version.V1_16_4)) - writePacket(PACKET_PLAYER_INFO); + writePacket(PacketSnapshots.PACKET_PLAYER_INFO); if (clientVersion.moreOrEqual(Version.V1_13)) { - writePacket(PACKET_DECLARE_COMMANDS); + writePacket(PacketSnapshots.PACKET_DECLARE_COMMANDS); - if (PACKET_PLUGIN_MESSAGE != null) - writePacket(PACKET_PLUGIN_MESSAGE); + if (PacketSnapshots.PACKET_PLUGIN_MESSAGE != null) + writePacket(PacketSnapshots.PACKET_PLUGIN_MESSAGE); } - if (PACKET_BOSS_BAR != null && clientVersion.moreOrEqual(Version.V1_9)) - writePacket(PACKET_BOSS_BAR); + if (PacketSnapshots.PACKET_BOSS_BAR != null && clientVersion.moreOrEqual(Version.V1_9)) + writePacket(PacketSnapshots.PACKET_BOSS_BAR); - if (PACKET_JOIN_MESSAGE != null) - writePacket(PACKET_JOIN_MESSAGE); + if (PacketSnapshots.PACKET_JOIN_MESSAGE != null) + writePacket(PacketSnapshots.PACKET_JOIN_MESSAGE); - if (PACKET_TITLE_TITLE != null) + if (PacketSnapshots.PACKET_TITLE_TITLE != null) writeTitle(); - if (PACKET_HEADER_AND_FOOTER != null) - writePacket(PACKET_HEADER_AND_FOOTER); + if (PacketSnapshots.PACKET_HEADER_AND_FOOTER != null) + writePacket(PacketSnapshots.PACKET_HEADER_AND_FOOTER); sendKeepAlive(); } @@ -276,13 +167,13 @@ public class ClientConnection extends ChannelInboundHandlerAdapter { public void writeTitle() { if (clientVersion.moreOrEqual(Version.V1_17)) { - writePacket(PACKET_TITLE_TITLE); - writePacket(PACKET_TITLE_SUBTITLE); - writePacket(PACKET_TITLE_TIMES); + writePacket(PacketSnapshots.PACKET_TITLE_TITLE); + writePacket(PacketSnapshots.PACKET_TITLE_SUBTITLE); + writePacket(PacketSnapshots.PACKET_TITLE_TIMES); } else { - writePacket(PACKET_TITLE_LEGACY_TITLE); - writePacket(PACKET_TITLE_LEGACY_SUBTITLE); - writePacket(PACKET_TITLE_LEGACY_TIMES); + writePacket(PacketSnapshots.PACKET_TITLE_LEGACY_TITLE); + writePacket(PacketSnapshots.PACKET_TITLE_LEGACY_SUBTITLE); + writePacket(PacketSnapshots.PACKET_TITLE_LEGACY_TIMES); } } @@ -313,25 +204,23 @@ public class ClientConnection extends ChannelInboundHandlerAdapter { return channel.isActive(); } - private void setPlayState() { - this.state = State.PLAY; - decoder.updateState(this.state); - encoder.updateState(this.state); - } - - public void updateStateAndVersion(State state, Version version) { + public void updateState(State state) { this.state = state; - decoder.updateVersion(version); decoder.updateState(state); - encoder.updateVersion(version); encoder.updateState(state); } - private void setAddress(String host) { + public void updateVersion(Version version) { + clientVersion = version; + decoder.updateVersion(version); + encoder.updateVersion(version); + } + + public void setAddress(String host) { this.address = new InetSocketAddress(host, ((InetSocketAddress)this.address).getPort()); } - private boolean checkBungeeGuardHandshake(String handshake) { + boolean checkBungeeGuardHandshake(String handshake) { String[] split = handshake.split("\00"); if (split.length != 4) @@ -370,7 +259,15 @@ public class ClientConnection extends ChannelInboundHandlerAdapter { return true; } - private boolean checkVelocityKeyIntegrity(ByteMessage buf) { + int getVelocityLoginMessageId() { + return velocityLoginMessageId; + } + + void setVelocityLoginMessageId(int velocityLoginMessageId) { + this.velocityLoginMessageId = velocityLoginMessageId; + } + + boolean checkVelocityKeyIntegrity(ByteMessage buf) { byte[] signature = new byte[32]; buf.readBytes(signature); byte[] data = new byte[buf.readableBytes()]; @@ -389,122 +286,4 @@ public class ClientConnection extends ChannelInboundHandlerAdapter { throw new IllegalStateException("Unsupported forwarding version " + version + ", wanted " + '\001'); return true; } - - public static void initPackets(LimboServer server) { - final String username = server.getConfig().getPingData().getVersion(); - final UUID uuid = UuidUtil.getOfflineModeUuid(username); - - PacketLoginSuccess loginSuccess = new PacketLoginSuccess(); - loginSuccess.setUsername(username); - loginSuccess.setUuid(uuid); - - PacketJoinGame joinGame = new PacketJoinGame(); - joinGame.setEntityId(0); - joinGame.setEnableRespawnScreen(true); - joinGame.setFlat(false); - joinGame.setGameMode(server.getConfig().getGameMode()); - joinGame.setHardcore(false); - joinGame.setMaxPlayers(server.getConfig().getMaxPlayers()); - joinGame.setPreviousGameMode(-1); - joinGame.setReducedDebugInfo(true); - joinGame.setDebug(false); - joinGame.setViewDistance(0); - joinGame.setWorldName("minecraft:world"); - joinGame.setWorldNames("minecraft:world"); - joinGame.setHashedSeed(0); - joinGame.setDimensionRegistry(server.getDimensionRegistry()); - - PacketPlayerAbilities playerAbilities = new PacketPlayerAbilities(); - playerAbilities.setFlyingSpeed(0.0F); - playerAbilities.setFlags(0x02); - playerAbilities.setFieldOfView(0.1F); - - PacketPlayerPositionAndLook positionAndLook = new PacketPlayerPositionAndLook(); - positionAndLook.setX(server.getConfig().getSpawnPosition().getX()); - positionAndLook.setY(server.getConfig().getSpawnPosition().getY()); - positionAndLook.setZ(server.getConfig().getSpawnPosition().getZ()); - positionAndLook.setYaw(server.getConfig().getSpawnPosition().getYaw()); - positionAndLook.setPitch(server.getConfig().getSpawnPosition().getPitch()); - positionAndLook.setTeleportId(ThreadLocalRandom.current().nextInt()); - - PacketDeclareCommands declareCommands = new PacketDeclareCommands(); - declareCommands.setCommands(Collections.emptyList()); - - PacketPlayerInfo info = new PacketPlayerInfo(); - info.setUsername(server.getConfig().getPlayerListUsername()); - info.setGameMode(server.getConfig().getGameMode()); - info.setUuid(uuid); - - PACKET_LOGIN_SUCCESS = PacketSnapshot.of(loginSuccess); - PACKET_JOIN_GAME = PacketSnapshot.of(joinGame); - PACKET_PLAYER_ABILITIES = PacketSnapshot.of(playerAbilities); - PACKET_PLAYER_POS = PacketSnapshot.of(positionAndLook); - PACKET_PLAYER_INFO = PacketSnapshot.of(info); - - PACKET_DECLARE_COMMANDS = PacketSnapshot.of(declareCommands); - - if (server.getConfig().isUseHeaderAndFooter()) { - PacketPlayerListHeader header = new PacketPlayerListHeader(); - header.setHeader(server.getConfig().getPlayerListHeader()); - header.setFooter(server.getConfig().getPlayerListFooter()); - PACKET_HEADER_AND_FOOTER = PacketSnapshot.of(header); - } - - if (server.getConfig().isUseBrandName()){ - PacketPluginMessage pluginMessage = new PacketPluginMessage(); - pluginMessage.setChannel(LimboConstants.BRAND_CHANNEL); - pluginMessage.setMessage(server.getConfig().getBrandName()); - PACKET_PLUGIN_MESSAGE = PacketSnapshot.of(pluginMessage); - } - - if (server.getConfig().isUseJoinMessage()) { - PacketChatMessage joinMessage = new PacketChatMessage(); - joinMessage.setJsonData(server.getConfig().getJoinMessage()); - joinMessage.setPosition(PacketChatMessage.Position.CHAT); - joinMessage.setSender(UUID.randomUUID()); - PACKET_JOIN_MESSAGE = PacketSnapshot.of(joinMessage); - } - - if (server.getConfig().isUseBossBar()) { - PacketBossBar bossBar = new PacketBossBar(); - bossBar.setBossBar(server.getConfig().getBossBar()); - bossBar.setUuid(UUID.randomUUID()); - PACKET_BOSS_BAR = PacketSnapshot.of(bossBar); - } - - if (server.getConfig().isUseTitle()) { - Title title = server.getConfig().getTitle(); - - PacketTitleSetTitle packetTitle = new PacketTitleSetTitle(); - PacketTitleSetSubTitle packetSubtitle = new PacketTitleSetSubTitle(); - PacketTitleTimes packetTimes = new PacketTitleTimes(); - - PacketTitleLegacy legacyTitle = new PacketTitleLegacy(); - PacketTitleLegacy legacySubtitle = new PacketTitleLegacy(); - PacketTitleLegacy legacyTimes = new PacketTitleLegacy(); - - packetTitle.setTitle(title.getTitle()); - packetSubtitle.setSubtitle(title.getSubtitle()); - packetTimes.setFadeIn(title.getFadeIn()); - packetTimes.setStay(title.getStay()); - packetTimes.setFadeOut(title.getFadeOut()); - - legacyTitle.setTitle(title); - legacyTitle.setAction(PacketTitleLegacy.Action.SET_TITLE); - - legacySubtitle.setTitle(title); - legacySubtitle.setAction(PacketTitleLegacy.Action.SET_SUBTITLE); - - legacyTimes.setTitle(title); - legacyTimes.setAction(PacketTitleLegacy.Action.SET_TIMES_AND_DISPLAY); - - PACKET_TITLE_TITLE = PacketSnapshot.of(packetTitle); - PACKET_TITLE_SUBTITLE = PacketSnapshot.of(packetSubtitle); - PACKET_TITLE_TIMES = PacketSnapshot.of(packetTimes); - - PACKET_TITLE_LEGACY_TITLE = PacketSnapshot.of(legacyTitle); - PACKET_TITLE_LEGACY_SUBTITLE = PacketSnapshot.of(legacySubtitle); - PACKET_TITLE_LEGACY_TIMES = PacketSnapshot.of(legacyTimes); - } - } } diff --git a/src/main/java/ru/nanit/limbo/connection/PacketHandler.java b/src/main/java/ru/nanit/limbo/connection/PacketHandler.java new file mode 100644 index 0000000..f28ac27 --- /dev/null +++ b/src/main/java/ru/nanit/limbo/connection/PacketHandler.java @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2020 Nan1t + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package ru.nanit.limbo.connection; + +import io.netty.buffer.Unpooled; +import ru.nanit.limbo.LimboConstants; +import ru.nanit.limbo.protocol.packets.PacketHandshake; +import ru.nanit.limbo.protocol.packets.login.PacketLoginPluginRequest; +import ru.nanit.limbo.protocol.packets.login.PacketLoginPluginResponse; +import ru.nanit.limbo.protocol.packets.login.PacketLoginStart; +import ru.nanit.limbo.protocol.packets.status.PacketStatusPing; +import ru.nanit.limbo.protocol.packets.status.PacketStatusRequest; +import ru.nanit.limbo.server.LimboServer; +import ru.nanit.limbo.server.Logger; +import ru.nanit.limbo.util.UuidUtil; + +import java.util.concurrent.ThreadLocalRandom; + +public class PacketHandler { + + private final LimboServer server; + + public PacketHandler(LimboServer server) { + this.server = server; + } + + public void handle(ClientConnection conn, PacketHandshake packet) { + conn.updateVersion(packet.getVersion()); + conn.updateState(packet.getNextState()); + + Logger.debug("Pinged from %s [%s]", conn.getAddress(), + conn.getClientVersion().toString()); + + if (server.getConfig().getInfoForwarding().isLegacy()) { + String[] split = packet.getHost().split("\00"); + + if (split.length == 3 || split.length == 4) { + conn.setAddress(split[1]); + conn.getGameProfile().setUuid(UuidUtil.fromString(split[2])); + } else { + conn.disconnectLogin("You've enabled player info forwarding. You need to connect with proxy"); + } + } else if (server.getConfig().getInfoForwarding().isBungeeGuard()) { + if (!conn.checkBungeeGuardHandshake(packet.getHost())) { + conn.disconnectLogin("Invalid BungeeGuard token or handshake format"); + } + } + } + + public void handle(ClientConnection conn, PacketStatusRequest packet) { + conn.sendPacket(PacketSnapshots.PACKET_STATUS_RESPONSE); + } + + public void handle(ClientConnection conn, PacketStatusPing packet) { + conn.sendPacketAndClose(packet); + } + + public void handle(ClientConnection conn, PacketLoginStart packet) { + if (server.getConfig().getMaxPlayers() > 0 && + server.getConnections().getCount() >= server.getConfig().getMaxPlayers()) { + conn.disconnectLogin("Too many players connected"); + return; + } + + if (!conn.getClientVersion().isSupported()) { + conn.disconnectLogin("Unsupported client version"); + return; + } + + if (server.getConfig().getInfoForwarding().isModern()) { + int loginId = ThreadLocalRandom.current().nextInt(0, Integer.MAX_VALUE); + PacketLoginPluginRequest request = new PacketLoginPluginRequest(); + + request.setMessageId(loginId); + request.setChannel(LimboConstants.VELOCITY_INFO_CHANNEL); + request.setData(Unpooled.EMPTY_BUFFER); + + conn.setVelocityLoginMessageId(loginId); + conn.sendPacket(request); + return; + } + + if (!server.getConfig().getInfoForwarding().isModern()) { + conn.getGameProfile().setUsername(packet.getUsername()); + conn.getGameProfile().setUuid(UuidUtil.getOfflineModeUuid(packet.getUsername())); + } + + conn.fireLoginSuccess(); + } + + public void handle(ClientConnection conn, PacketLoginPluginResponse packet) { + if (server.getConfig().getInfoForwarding().isModern() + && packet.getMessageId() == conn.getVelocityLoginMessageId()) { + + if (!packet.isSuccessful() || packet.getData() == null) { + conn.disconnectLogin("You need to connect with Velocity"); + return; + } + + if (!conn.checkVelocityKeyIntegrity(packet.getData())) { + conn.disconnectLogin("Can't verify forwarded player info"); + return; + } + + // Order is important + conn.setAddress(packet.getData().readString()); + conn.getGameProfile().setUuid(packet.getData().readUuid()); + conn.getGameProfile().setUsername(packet.getData().readString()); + + conn.fireLoginSuccess(); + } + } + +} diff --git a/src/main/java/ru/nanit/limbo/connection/PacketSnapshots.java b/src/main/java/ru/nanit/limbo/connection/PacketSnapshots.java new file mode 100644 index 0000000..9fc1d48 --- /dev/null +++ b/src/main/java/ru/nanit/limbo/connection/PacketSnapshots.java @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2020 Nan1t + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package ru.nanit.limbo.connection; + +import ru.nanit.limbo.LimboConstants; +import ru.nanit.limbo.protocol.PacketSnapshot; +import ru.nanit.limbo.protocol.packets.login.PacketLoginSuccess; +import ru.nanit.limbo.protocol.packets.play.*; +import ru.nanit.limbo.protocol.packets.status.PacketStatusResponse; +import ru.nanit.limbo.server.LimboServer; +import ru.nanit.limbo.server.data.Title; +import ru.nanit.limbo.util.UuidUtil; + +import java.util.Collections; +import java.util.UUID; +import java.util.concurrent.ThreadLocalRandom; + +public final class PacketSnapshots { + + public static PacketSnapshot PACKET_STATUS_RESPONSE; + public static PacketSnapshot PACKET_LOGIN_SUCCESS; + public static PacketSnapshot PACKET_JOIN_GAME; + public static PacketSnapshot PACKET_PLUGIN_MESSAGE; + public static PacketSnapshot PACKET_PLAYER_ABILITIES; + public static PacketSnapshot PACKET_PLAYER_INFO; + public static PacketSnapshot PACKET_DECLARE_COMMANDS; + public static PacketSnapshot PACKET_PLAYER_POS; + public static PacketSnapshot PACKET_JOIN_MESSAGE; + public static PacketSnapshot PACKET_BOSS_BAR; + public static PacketSnapshot PACKET_HEADER_AND_FOOTER; + + public static PacketSnapshot PACKET_TITLE_TITLE; + public static PacketSnapshot PACKET_TITLE_SUBTITLE; + public static PacketSnapshot PACKET_TITLE_TIMES; + + public static PacketSnapshot PACKET_TITLE_LEGACY_TITLE; + public static PacketSnapshot PACKET_TITLE_LEGACY_SUBTITLE; + public static PacketSnapshot PACKET_TITLE_LEGACY_TIMES; + + private PacketSnapshots() { } + + public static void initPackets(LimboServer server) { + final String username = server.getConfig().getPingData().getVersion(); + final UUID uuid = UuidUtil.getOfflineModeUuid(username); + + PacketLoginSuccess loginSuccess = new PacketLoginSuccess(); + loginSuccess.setUsername(username); + loginSuccess.setUuid(uuid); + + PacketJoinGame joinGame = new PacketJoinGame(); + joinGame.setEntityId(0); + joinGame.setEnableRespawnScreen(true); + joinGame.setFlat(false); + joinGame.setGameMode(server.getConfig().getGameMode()); + joinGame.setHardcore(false); + joinGame.setMaxPlayers(server.getConfig().getMaxPlayers()); + joinGame.setPreviousGameMode(-1); + joinGame.setReducedDebugInfo(true); + joinGame.setDebug(false); + joinGame.setViewDistance(0); + joinGame.setWorldName("minecraft:world"); + joinGame.setWorldNames("minecraft:world"); + joinGame.setHashedSeed(0); + joinGame.setDimensionRegistry(server.getDimensionRegistry()); + + PacketPlayerAbilities playerAbilities = new PacketPlayerAbilities(); + playerAbilities.setFlyingSpeed(0.0F); + playerAbilities.setFlags(0x02); + playerAbilities.setFieldOfView(0.1F); + + PacketPlayerPositionAndLook positionAndLook = new PacketPlayerPositionAndLook(); + positionAndLook.setX(server.getConfig().getSpawnPosition().getX()); + positionAndLook.setY(server.getConfig().getSpawnPosition().getY()); + positionAndLook.setZ(server.getConfig().getSpawnPosition().getZ()); + positionAndLook.setYaw(server.getConfig().getSpawnPosition().getYaw()); + positionAndLook.setPitch(server.getConfig().getSpawnPosition().getPitch()); + positionAndLook.setTeleportId(ThreadLocalRandom.current().nextInt()); + + PacketDeclareCommands declareCommands = new PacketDeclareCommands(); + declareCommands.setCommands(Collections.emptyList()); + + PacketPlayerInfo info = new PacketPlayerInfo(); + info.setUsername(server.getConfig().getPlayerListUsername()); + info.setGameMode(server.getConfig().getGameMode()); + info.setUuid(uuid); + + PACKET_STATUS_RESPONSE = PacketSnapshot.of(new PacketStatusResponse(server)); + PACKET_LOGIN_SUCCESS = PacketSnapshot.of(loginSuccess); + PACKET_JOIN_GAME = PacketSnapshot.of(joinGame); + PACKET_PLAYER_ABILITIES = PacketSnapshot.of(playerAbilities); + PACKET_PLAYER_POS = PacketSnapshot.of(positionAndLook); + PACKET_PLAYER_INFO = PacketSnapshot.of(info); + + PACKET_DECLARE_COMMANDS = PacketSnapshot.of(declareCommands); + + if (server.getConfig().isUseHeaderAndFooter()) { + PacketPlayerListHeader header = new PacketPlayerListHeader(); + header.setHeader(server.getConfig().getPlayerListHeader()); + header.setFooter(server.getConfig().getPlayerListFooter()); + PACKET_HEADER_AND_FOOTER = PacketSnapshot.of(header); + } + + if (server.getConfig().isUseBrandName()){ + PacketPluginMessage pluginMessage = new PacketPluginMessage(); + pluginMessage.setChannel(LimboConstants.BRAND_CHANNEL); + pluginMessage.setMessage(server.getConfig().getBrandName()); + PACKET_PLUGIN_MESSAGE = PacketSnapshot.of(pluginMessage); + } + + if (server.getConfig().isUseJoinMessage()) { + PacketChatMessage joinMessage = new PacketChatMessage(); + joinMessage.setJsonData(server.getConfig().getJoinMessage()); + joinMessage.setPosition(PacketChatMessage.Position.CHAT); + joinMessage.setSender(UUID.randomUUID()); + PACKET_JOIN_MESSAGE = PacketSnapshot.of(joinMessage); + } + + if (server.getConfig().isUseBossBar()) { + PacketBossBar bossBar = new PacketBossBar(); + bossBar.setBossBar(server.getConfig().getBossBar()); + bossBar.setUuid(UUID.randomUUID()); + PACKET_BOSS_BAR = PacketSnapshot.of(bossBar); + } + + if (server.getConfig().isUseTitle()) { + Title title = server.getConfig().getTitle(); + + PacketTitleSetTitle packetTitle = new PacketTitleSetTitle(); + PacketTitleSetSubTitle packetSubtitle = new PacketTitleSetSubTitle(); + PacketTitleTimes packetTimes = new PacketTitleTimes(); + + PacketTitleLegacy legacyTitle = new PacketTitleLegacy(); + PacketTitleLegacy legacySubtitle = new PacketTitleLegacy(); + PacketTitleLegacy legacyTimes = new PacketTitleLegacy(); + + packetTitle.setTitle(title.getTitle()); + packetSubtitle.setSubtitle(title.getSubtitle()); + packetTimes.setFadeIn(title.getFadeIn()); + packetTimes.setStay(title.getStay()); + packetTimes.setFadeOut(title.getFadeOut()); + + legacyTitle.setTitle(title); + legacyTitle.setAction(PacketTitleLegacy.Action.SET_TITLE); + + legacySubtitle.setTitle(title); + legacySubtitle.setAction(PacketTitleLegacy.Action.SET_SUBTITLE); + + legacyTimes.setTitle(title); + legacyTimes.setAction(PacketTitleLegacy.Action.SET_TIMES_AND_DISPLAY); + + PACKET_TITLE_TITLE = PacketSnapshot.of(packetTitle); + PACKET_TITLE_SUBTITLE = PacketSnapshot.of(packetSubtitle); + PACKET_TITLE_TIMES = PacketSnapshot.of(packetTimes); + + PACKET_TITLE_LEGACY_TITLE = PacketSnapshot.of(legacyTitle); + PACKET_TITLE_LEGACY_SUBTITLE = PacketSnapshot.of(legacySubtitle); + PACKET_TITLE_LEGACY_TIMES = PacketSnapshot.of(legacyTimes); + } + } +} diff --git a/src/main/java/ru/nanit/limbo/protocol/Packet.java b/src/main/java/ru/nanit/limbo/protocol/Packet.java index 3df6dcf..2663860 100644 --- a/src/main/java/ru/nanit/limbo/protocol/Packet.java +++ b/src/main/java/ru/nanit/limbo/protocol/Packet.java @@ -17,7 +17,9 @@ package ru.nanit.limbo.protocol; +import ru.nanit.limbo.connection.ClientConnection; import ru.nanit.limbo.protocol.registry.Version; +import ru.nanit.limbo.server.LimboServer; public interface Packet { @@ -25,4 +27,8 @@ public interface Packet { void decode(ByteMessage msg, Version version); + default void handle(ClientConnection conn, LimboServer server) { + // Ignored by default + } + } diff --git a/src/main/java/ru/nanit/limbo/protocol/packets/PacketHandshake.java b/src/main/java/ru/nanit/limbo/protocol/packets/PacketHandshake.java index 31c475b..3e0157b 100644 --- a/src/main/java/ru/nanit/limbo/protocol/packets/PacketHandshake.java +++ b/src/main/java/ru/nanit/limbo/protocol/packets/PacketHandshake.java @@ -17,10 +17,14 @@ package ru.nanit.limbo.protocol.packets; +import ru.nanit.limbo.connection.ClientConnection; import ru.nanit.limbo.protocol.ByteMessage; import ru.nanit.limbo.protocol.PacketIn; import ru.nanit.limbo.protocol.registry.State; import ru.nanit.limbo.protocol.registry.Version; +import ru.nanit.limbo.server.LimboServer; +import ru.nanit.limbo.server.Logger; +import ru.nanit.limbo.util.UuidUtil; public class PacketHandshake implements PacketIn { @@ -62,4 +66,9 @@ public class PacketHandshake implements PacketIn { public String toString() { return getClass().getSimpleName(); } + + @Override + public void handle(ClientConnection conn, LimboServer server) { + server.getPacketHandler().handle(conn, this); + } } diff --git a/src/main/java/ru/nanit/limbo/protocol/packets/login/PacketLoginPluginResponse.java b/src/main/java/ru/nanit/limbo/protocol/packets/login/PacketLoginPluginResponse.java index 126ca29..c0ab46a 100644 --- a/src/main/java/ru/nanit/limbo/protocol/packets/login/PacketLoginPluginResponse.java +++ b/src/main/java/ru/nanit/limbo/protocol/packets/login/PacketLoginPluginResponse.java @@ -17,9 +17,11 @@ package ru.nanit.limbo.protocol.packets.login; +import ru.nanit.limbo.connection.ClientConnection; import ru.nanit.limbo.protocol.ByteMessage; import ru.nanit.limbo.protocol.PacketIn; import ru.nanit.limbo.protocol.registry.Version; +import ru.nanit.limbo.server.LimboServer; public class PacketLoginPluginResponse implements PacketIn { @@ -50,6 +52,11 @@ public class PacketLoginPluginResponse implements PacketIn { } } + @Override + public void handle(ClientConnection conn, LimboServer server) { + server.getPacketHandler().handle(conn, this); + } + @Override public String toString() { return getClass().getSimpleName(); diff --git a/src/main/java/ru/nanit/limbo/protocol/packets/login/PacketLoginStart.java b/src/main/java/ru/nanit/limbo/protocol/packets/login/PacketLoginStart.java index 4c8ea4c..c555a62 100644 --- a/src/main/java/ru/nanit/limbo/protocol/packets/login/PacketLoginStart.java +++ b/src/main/java/ru/nanit/limbo/protocol/packets/login/PacketLoginStart.java @@ -17,9 +17,11 @@ package ru.nanit.limbo.protocol.packets.login; +import ru.nanit.limbo.connection.ClientConnection; import ru.nanit.limbo.protocol.ByteMessage; import ru.nanit.limbo.protocol.PacketIn; import ru.nanit.limbo.protocol.registry.Version; +import ru.nanit.limbo.server.LimboServer; public class PacketLoginStart implements PacketIn { @@ -34,6 +36,11 @@ public class PacketLoginStart implements PacketIn { this.username = msg.readString(); } + @Override + public void handle(ClientConnection conn, LimboServer server) { + server.getPacketHandler().handle(conn, this); + } + @Override public String toString() { return getClass().getSimpleName(); diff --git a/src/main/java/ru/nanit/limbo/protocol/packets/status/PacketStatusPing.java b/src/main/java/ru/nanit/limbo/protocol/packets/status/PacketStatusPing.java index 3bc39ee..684ed89 100644 --- a/src/main/java/ru/nanit/limbo/protocol/packets/status/PacketStatusPing.java +++ b/src/main/java/ru/nanit/limbo/protocol/packets/status/PacketStatusPing.java @@ -17,9 +17,11 @@ package ru.nanit.limbo.protocol.packets.status; +import ru.nanit.limbo.connection.ClientConnection; import ru.nanit.limbo.protocol.ByteMessage; import ru.nanit.limbo.protocol.Packet; import ru.nanit.limbo.protocol.registry.Version; +import ru.nanit.limbo.server.LimboServer; public class PacketStatusPing implements Packet { @@ -35,6 +37,11 @@ public class PacketStatusPing implements Packet { this.randomId = msg.readLong(); } + @Override + public void handle(ClientConnection conn, LimboServer server) { + server.getPacketHandler().handle(conn, this); + } + @Override public String toString() { return getClass().getSimpleName(); diff --git a/src/main/java/ru/nanit/limbo/protocol/packets/status/PacketStatusRequest.java b/src/main/java/ru/nanit/limbo/protocol/packets/status/PacketStatusRequest.java index ce9759c..9865b35 100644 --- a/src/main/java/ru/nanit/limbo/protocol/packets/status/PacketStatusRequest.java +++ b/src/main/java/ru/nanit/limbo/protocol/packets/status/PacketStatusRequest.java @@ -17,9 +17,11 @@ package ru.nanit.limbo.protocol.packets.status; +import ru.nanit.limbo.connection.ClientConnection; import ru.nanit.limbo.protocol.ByteMessage; import ru.nanit.limbo.protocol.PacketIn; import ru.nanit.limbo.protocol.registry.Version; +import ru.nanit.limbo.server.LimboServer; public class PacketStatusRequest implements PacketIn { @@ -28,6 +30,11 @@ public class PacketStatusRequest implements PacketIn { } + @Override + public void handle(ClientConnection conn, LimboServer server) { + server.getPacketHandler().handle(conn, this); + } + @Override public String toString() { return getClass().getSimpleName(); diff --git a/src/main/java/ru/nanit/limbo/server/LimboServer.java b/src/main/java/ru/nanit/limbo/server/LimboServer.java index ba8fc8e..c2f06ce 100644 --- a/src/main/java/ru/nanit/limbo/server/LimboServer.java +++ b/src/main/java/ru/nanit/limbo/server/LimboServer.java @@ -30,6 +30,8 @@ import io.netty.util.ResourceLeakDetector; import ru.nanit.limbo.configuration.LimboConfig; import ru.nanit.limbo.connection.ClientChannelInitializer; import ru.nanit.limbo.connection.ClientConnection; +import ru.nanit.limbo.connection.PacketHandler; +import ru.nanit.limbo.connection.PacketSnapshots; import ru.nanit.limbo.world.dimension.DimensionRegistry; import java.nio.file.Paths; @@ -39,6 +41,7 @@ import java.util.concurrent.TimeUnit; public final class LimboServer { private LimboConfig config; + private PacketHandler packetHandler; private Connections connections; private DimensionRegistry dimensionRegistry; private ScheduledFuture keepAliveTask; @@ -50,6 +53,10 @@ public final class LimboServer { return config; } + public PacketHandler getPacketHandler() { + return packetHandler; + } + public Connections getConnections() { return connections; } @@ -66,11 +73,12 @@ public final class LimboServer { config = new LimboConfig(Paths.get("./")); config.load(); + packetHandler = new PacketHandler(this); dimensionRegistry = new DimensionRegistry(this); dimensionRegistry.load(config.getDimensionType()); connections = new Connections(); - ClientConnection.initPackets(this); + PacketSnapshots.initPackets(this); startBootstrap();