Added packet pre-encoding. Code style.

This commit is contained in:
Nan1t 2020-11-28 18:49:18 +02:00
parent 95289e169c
commit cc251c17e2
8 changed files with 207 additions and 183 deletions

View File

@ -6,6 +6,8 @@ import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelInboundHandlerAdapter;
import ru.nanit.limbo.LimboConstants; import ru.nanit.limbo.LimboConstants;
import ru.nanit.limbo.protocol.ByteMessage;
import ru.nanit.limbo.protocol.PreRenderedPacket;
import ru.nanit.limbo.protocol.packets.login.*; import ru.nanit.limbo.protocol.packets.login.*;
import ru.nanit.limbo.protocol.packets.play.*; import ru.nanit.limbo.protocol.packets.play.*;
import ru.nanit.limbo.protocol.pipeline.PacketDecoder; import ru.nanit.limbo.protocol.pipeline.PacketDecoder;
@ -19,18 +21,29 @@ import ru.nanit.limbo.protocol.registry.Version;
import ru.nanit.limbo.server.LimboServer; import ru.nanit.limbo.server.LimboServer;
import ru.nanit.limbo.util.Logger; import ru.nanit.limbo.util.Logger;
import ru.nanit.limbo.util.UuidUtil; import ru.nanit.limbo.util.UuidUtil;
import ru.nanit.limbo.util.VelocityUtil;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.SocketAddress; import java.net.SocketAddress;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.ThreadLocalRandom;
public class ClientConnection extends ChannelInboundHandlerAdapter { public class ClientConnection extends ChannelInboundHandlerAdapter {
private static PreRenderedPacket PACKET_LOGIN_SUCCESS;
private static PreRenderedPacket PACKET_JOIN_GAME;
private static PreRenderedPacket PACKET_PLAYER_ABILITIES;
private static PreRenderedPacket PACKET_PLAYER_INFO;
private static PreRenderedPacket PACKET_PLAYER_POS;
private static PreRenderedPacket PACKET_JOIN_MESSAGE;
private static PreRenderedPacket PACKET_BOSS_BAR;
private final LimboServer server; private final LimboServer server;
private final Channel channel; private final Channel channel;
private final GameProfile profile; private final GameProfile gameProfile;
private State state; private State state;
private Version clientVersion; private Version clientVersion;
@ -42,26 +55,25 @@ public class ClientConnection extends ChannelInboundHandlerAdapter {
this.server = server; this.server = server;
this.channel = channel; this.channel = channel;
this.address = channel.remoteAddress(); this.address = channel.remoteAddress();
this.profile = new GameProfile(); this.gameProfile = new GameProfile();
} }
public UUID getUuid() { public UUID getUuid() {
return profile.getUuid(); return gameProfile.getUuid();
} }
public String getUsername(){ public String getUsername(){
return profile.getUsername(); return gameProfile.getUsername();
} }
private void setAddress(String host){ public SocketAddress getAddress() {
this.address = new InetSocketAddress(host, ((InetSocketAddress)this.address).getPort()); return address;
} }
@Override @Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception { public void channelInactive(ChannelHandlerContext ctx) throws Exception {
if (state.equals(State.PLAY)){ if (state.equals(State.PLAY)){
server.getConnections().removeConnection(this); server.getConnections().removeConnection(this);
Logger.info("Player %s disconnected", getUsername());
} }
super.channelInactive(ctx); super.channelInactive(ctx);
} }
@ -90,29 +102,32 @@ public class ClientConnection extends ChannelInboundHandlerAdapter {
if (split.length == 3 || split.length == 4){ if (split.length == 3 || split.length == 4){
setAddress(split[1]); setAddress(split[1]);
profile.setUuid(UuidUtil.fromString(split[2])); gameProfile.setUuid(UuidUtil.fromString(split[2]));
} else { } else {
disconnect("You've enabled player info forwarding. You need to connect with proxy"); disconnectLogin("You've enabled player info forwarding. You need to connect with proxy");
} }
} }
return;
} }
if (packet instanceof PacketStatusRequest){ if (packet instanceof PacketStatusRequest){
sendPacket(new PacketStatusResponse(server)); sendPacket(new PacketStatusResponse(server));
return;
} }
if (packet instanceof PacketStatusPing){ if (packet instanceof PacketStatusPing){
sendPacketAndClose(packet); sendPacketAndClose(packet);
return;
} }
if (packet instanceof PacketLoginStart){ if (packet instanceof PacketLoginStart){
if (server.getConnections().getCount() >= server.getConfig().getMaxPlayers()){ if (server.getConnections().getCount() >= server.getConfig().getMaxPlayers()){
disconnect("Too many players connected"); disconnectLogin("Too many players connected");
return; return;
} }
if (!clientVersion.equals(Version.getCurrentSupported())){ if (!clientVersion.equals(Version.getCurrentSupported())){
disconnect("Incompatible client version"); disconnectLogin("Incompatible client version");
return; return;
} }
@ -127,13 +142,12 @@ public class ClientConnection extends ChannelInboundHandlerAdapter {
} }
if (!server.getConfig().getInfoForwarding().isModern()){ if (!server.getConfig().getInfoForwarding().isModern()){
profile.setUsername(((PacketLoginStart) packet).getUsername()); gameProfile.setUsername(((PacketLoginStart)packet).getUsername());
gameProfile.setUuid(UuidUtil.getOfflineModeUuid(getUsername()));
if (profile.getUuid() == null)
profile.setUuid(UuidUtil.getOfflineModeUuid(getUsername()));
} }
fireLoginSuccess(); fireLoginSuccess();
return;
} }
if (packet instanceof PacketLoginPluginResponse){ if (packet instanceof PacketLoginPluginResponse){
@ -143,18 +157,19 @@ public class ClientConnection extends ChannelInboundHandlerAdapter {
&& response.getMessageId() == velocityLoginMessageId){ && response.getMessageId() == velocityLoginMessageId){
if (!response.isSuccessful() || response.getData() == null){ if (!response.isSuccessful() || response.getData() == null){
disconnect("You need to connect with Velocity"); disconnectLogin("You need to connect with Velocity");
return; return;
} }
if (!VelocityUtil.checkIntegrity(response.getData())) { if (!checkVelocityKeyIntegrity(response.getData())) {
disconnect("Can't verify forwarded player info"); disconnectLogin("Can't verify forwarded player info");
return; return;
} }
// Order is important
setAddress(response.getData().readString()); setAddress(response.getData().readString());
profile.setUuid(response.getData().readUuid()); gameProfile.setUuid(response.getData().readUuid());
profile.setUsername(response.getData().readString()); gameProfile.setUsername(response.getData().readString());
fireLoginSuccess(); fireLoginSuccess();
} }
@ -163,79 +178,30 @@ public class ClientConnection extends ChannelInboundHandlerAdapter {
private void fireLoginSuccess(){ private void fireLoginSuccess(){
if (server.getConfig().getInfoForwarding().isModern() && velocityLoginMessageId == -1){ if (server.getConfig().getInfoForwarding().isModern() && velocityLoginMessageId == -1){
disconnect("You need to connect with Velocity"); disconnectLogin("You need to connect with Velocity");
return; return;
} }
PacketLoginSuccess loginSuccess = new PacketLoginSuccess(); sendPacket(PACKET_LOGIN_SUCCESS);
loginSuccess.setUuid(UuidUtil.getOfflineModeUuid(getUsername()));
loginSuccess.setUsername(getUsername());
sendPacket(loginSuccess);
updateState(State.PLAY); updateState(State.PLAY);
server.getConnections().addConnection(this); server.getConnections().addConnection(this);
Logger.info("Player %s connected (%s)", getUsername(), address); sendPacket(PACKET_JOIN_GAME);
sendPacket(PACKET_PLAYER_ABILITIES);
sendJoinPackets(); sendPacket(PACKET_PLAYER_POS);
} sendPacket(PACKET_PLAYER_INFO);
private void sendJoinPackets(){
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(false);
joinGame.setDebug(false);
joinGame.setViewDistance(2);
joinGame.setWorldName("minecraft:world");
joinGame.setWorldNames("minecraft:world");
joinGame.setHashedSeed(0);
joinGame.setDimensionCodec(server.getDimensionRegistry().getCodec());
joinGame.setDimension(server.getDimensionRegistry().getDefaultDimension());
PacketPlayerAbilities abilities = new PacketPlayerAbilities();
abilities.setFlyingSpeed(0.0F);
abilities.setFlags(0x02);
abilities.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());
PacketPlayerInfo info = new PacketPlayerInfo();
info.setConnection(this);
info.setGameMode(server.getConfig().getGameMode());
sendPacket(joinGame);
sendPacket(abilities);
sendPacket(positionAndLook);
sendPacket(info);
sendKeepAlive(); sendKeepAlive();
if (server.getJoinMessage() != null){ if (PACKET_BOSS_BAR != null)
sendPacket(server.getJoinMessage()); sendPacket(PACKET_BOSS_BAR);
if (PACKET_JOIN_MESSAGE != null)
sendPacket(PACKET_JOIN_MESSAGE);
} }
if (server.getJoinBossBar() != null){ public void disconnectLogin(String reason){
sendPacket(server.getJoinBossBar());
}
}
public void disconnect(String reason){
if (isConnected() && state == State.LOGIN){ if (isConnected() && state == State.LOGIN){
PacketDisconnect disconnect = new PacketDisconnect(); PacketDisconnect disconnect = new PacketDisconnect();
disconnect.setReason(reason); disconnect.setReason(reason);
@ -265,10 +231,98 @@ public class ClientConnection extends ChannelInboundHandlerAdapter {
return channel.isActive(); return channel.isActive();
} }
public void updateState(State state){ private void updateState(State state){
this.state = state; this.state = state;
channel.pipeline().get(PacketDecoder.class).updateState(state); channel.pipeline().get(PacketDecoder.class).updateState(state);
channel.pipeline().get(PacketEncoder.class).updateState(state); channel.pipeline().get(PacketEncoder.class).updateState(state);
} }
private void setAddress(String host){
this.address = new InetSocketAddress(host, ((InetSocketAddress)this.address).getPort());
}
private boolean checkVelocityKeyIntegrity(ByteMessage buf) {
byte[] signature = new byte[32];
buf.readBytes(signature);
byte[] data = new byte[buf.readableBytes()];
buf.getBytes(buf.readerIndex(), data);
try {
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(server.getConfig().getInfoForwarding().getSecretKey(), "HmacSHA256"));
byte[] mySignature = mac.doFinal(data);
if (!MessageDigest.isEqual(signature, mySignature))
return false;
} catch (InvalidKeyException |java.security.NoSuchAlgorithmException e) {
throw new AssertionError(e);
}
int version = buf.readVarInt();
if (version != 1)
throw new IllegalStateException("Unsupported forwarding version " + version + ", wanted " + '\001');
return true;
}
public static void preInitPackets(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(2);
joinGame.setWorldName("minecraft:world");
joinGame.setWorldNames("minecraft:world");
joinGame.setHashedSeed(0);
joinGame.setDimensionCodec(server.getDimensionRegistry().getCodec());
joinGame.setDimension(server.getDimensionRegistry().getDefaultDimension());
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());
PacketPlayerInfo info = new PacketPlayerInfo();
info.setUsername(username);
info.setGameMode(server.getConfig().getGameMode());
info.setUuid(uuid);
PACKET_LOGIN_SUCCESS = PreRenderedPacket.of(loginSuccess);
PACKET_JOIN_GAME = PreRenderedPacket.of(joinGame);
PACKET_PLAYER_ABILITIES = PreRenderedPacket.of(playerAbilities);
PACKET_PLAYER_POS = PreRenderedPacket.of(positionAndLook);
PACKET_PLAYER_INFO = PreRenderedPacket.of(info);
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 = PreRenderedPacket.of(joinMessage);
}
if (server.getConfig().isUseBossBar()){
PacketBossBar bossBar = new PacketBossBar();
bossBar.setBossBar(server.getConfig().getBossBar());
bossBar.setUuid(UUID.randomUUID());
PACKET_BOSS_BAR = PreRenderedPacket.of(bossBar);
}
}
} }

View File

@ -4,22 +4,22 @@ import java.util.UUID;
public class GameProfile { public class GameProfile {
private String username;
private UUID uuid; private UUID uuid;
private String username;
public String getUsername() {
return username;
}
public UUID getUuid() { public UUID getUuid() {
return uuid; return uuid;
} }
public void setUsername(String username) {
this.username = username;
}
public void setUuid(UUID uuid) { public void setUuid(UUID uuid) {
this.uuid = uuid; this.uuid = uuid;
} }
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
} }

View File

@ -0,0 +1,31 @@
package ru.nanit.limbo.protocol;
public class PreRenderedPacket implements PacketOut {
private final PacketOut packet;
private byte[] message;
public PreRenderedPacket(PacketOut packet){
this.packet = packet;
}
public PacketOut getWrappedPacket(){
return packet;
}
public PreRenderedPacket render(){
ByteMessage renderedMessage = ByteMessage.create();
packet.encode(renderedMessage);
this.message = renderedMessage.toByteArray();
return this;
}
@Override
public void encode(ByteMessage msg) {
msg.writeBytes(message);
}
public static PreRenderedPacket of(PacketOut packet){
return new PreRenderedPacket(packet).render();
}
}

View File

@ -1,31 +1,37 @@
package ru.nanit.limbo.protocol.packets.play; package ru.nanit.limbo.protocol.packets.play;
import ru.nanit.limbo.connection.ClientConnection;
import ru.nanit.limbo.protocol.ByteMessage; import ru.nanit.limbo.protocol.ByteMessage;
import ru.nanit.limbo.protocol.PacketOut; import ru.nanit.limbo.protocol.PacketOut;
import java.util.UUID;
/** /**
* This packet wrapper used only for ADD_PLAYER action * This packet was very simplified and using only for ADD_PLAYER action
*/ */
public class PacketPlayerInfo implements PacketOut { public class PacketPlayerInfo implements PacketOut {
private int gameMode; private int gameMode = 3;
private ClientConnection connection; private String username = "";
private UUID uuid;
public void setConnection(ClientConnection connection) {
this.connection = connection;
}
public void setGameMode(int gameMode) { public void setGameMode(int gameMode) {
this.gameMode = gameMode; this.gameMode = gameMode;
} }
public void setUsername(String username){
this.username = username;
}
public void setUuid(UUID uuid){
this.uuid = uuid;
}
@Override @Override
public void encode(ByteMessage msg) { public void encode(ByteMessage msg) {
msg.writeVarInt(0); msg.writeVarInt(0);
msg.writeVarInt(1); msg.writeVarInt(1);
msg.writeUuid(connection.getUuid()); msg.writeUuid(uuid);
msg.writeString(connection.getUsername()); msg.writeString(username);
msg.writeVarInt(0); msg.writeVarInt(0);
msg.writeVarInt(gameMode); msg.writeVarInt(gameMode);
msg.writeVarInt(60); msg.writeVarInt(60);

View File

@ -5,6 +5,7 @@ import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder; import io.netty.handler.codec.MessageToByteEncoder;
import ru.nanit.limbo.protocol.ByteMessage; import ru.nanit.limbo.protocol.ByteMessage;
import ru.nanit.limbo.protocol.Packet; import ru.nanit.limbo.protocol.Packet;
import ru.nanit.limbo.protocol.PreRenderedPacket;
import ru.nanit.limbo.protocol.registry.State; import ru.nanit.limbo.protocol.registry.State;
import ru.nanit.limbo.util.Logger; import ru.nanit.limbo.util.Logger;
@ -21,7 +22,13 @@ public class PacketEncoder extends MessageToByteEncoder<Packet> {
if (registry == null) return; if (registry == null) return;
ByteMessage msg = new ByteMessage(out); ByteMessage msg = new ByteMessage(out);
int packetId = registry.getPacketId(packet.getClass()); int packetId;
if (packet instanceof PreRenderedPacket){
packetId = registry.getPacketId(((PreRenderedPacket)packet).getWrappedPacket().getClass());
} else {
packetId = registry.getPacketId(packet.getClass());
}
if (packetId == -1){ if (packetId == -1){
Logger.warning("Undefined packet class: %s", packet.getClass().getName()); Logger.warning("Undefined packet class: %s", packet.getClass().getName());

View File

@ -1,6 +1,7 @@
package ru.nanit.limbo.server; package ru.nanit.limbo.server;
import ru.nanit.limbo.connection.ClientConnection; import ru.nanit.limbo.connection.ClientConnection;
import ru.nanit.limbo.util.Logger;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
@ -26,9 +27,11 @@ public final class Connections {
public void addConnection(ClientConnection connection){ public void addConnection(ClientConnection connection){
connections.put(connection.getUuid(), connection); connections.put(connection.getUuid(), connection);
Logger.info("Player %s connected (%s)", connection.getUsername(), connection.getAddress());
} }
public void removeConnection(ClientConnection connection){ public void removeConnection(ClientConnection connection){
connections.remove(connection.getUuid()); connections.remove(connection.getUuid());
Logger.info("Player %s disconnected", connection.getUsername());
} }
} }

View File

@ -8,16 +8,12 @@ import ru.nanit.limbo.configuration.LimboConfig;
import ru.nanit.limbo.configuration.SocketAddressSerializer; import ru.nanit.limbo.configuration.SocketAddressSerializer;
import ru.nanit.limbo.connection.ClientChannelInitializer; import ru.nanit.limbo.connection.ClientChannelInitializer;
import ru.nanit.limbo.connection.ClientConnection; import ru.nanit.limbo.connection.ClientConnection;
import ru.nanit.limbo.protocol.packets.play.PacketBossBar;
import ru.nanit.limbo.protocol.packets.play.PacketChatMessage;
import ru.nanit.limbo.server.data.*; import ru.nanit.limbo.server.data.*;
import ru.nanit.limbo.util.Logger; import ru.nanit.limbo.util.Logger;
import ru.nanit.limbo.util.VelocityUtil;
import ru.nanit.limbo.world.DimensionRegistry; import ru.nanit.limbo.world.DimensionRegistry;
import java.net.SocketAddress; import java.net.SocketAddress;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.UUID;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -28,9 +24,6 @@ public final class LimboServer {
private Connections connections; private Connections connections;
private DimensionRegistry dimensionRegistry; private DimensionRegistry dimensionRegistry;
private PacketChatMessage joinMessage;
private PacketBossBar joinBossBar;
public LimboConfig getConfig(){ public LimboConfig getConfig(){
return config; return config;
} }
@ -43,14 +36,6 @@ public final class LimboServer {
return dimensionRegistry; return dimensionRegistry;
} }
public PacketChatMessage getJoinMessage() {
return joinMessage;
}
public PacketBossBar getJoinBossBar() {
return joinBossBar;
}
public void start() throws Exception { public void start() throws Exception {
Logger.info("Starting server..."); Logger.info("Starting server...");
@ -65,16 +50,11 @@ public final class LimboServer {
Logger.setLevel(config.getDebugLevel()); Logger.setLevel(config.getDebugLevel());
if (config.getInfoForwarding().isModern()){
VelocityUtil.init(config);
}
dimensionRegistry = new DimensionRegistry(); dimensionRegistry = new DimensionRegistry();
dimensionRegistry.load(config.getDimensionType()); dimensionRegistry.load(config.getDimensionType());
connections = new Connections(); connections = new Connections();
initInGameData(); ClientConnection.preInitPackets(this);
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
executor.scheduleAtFixedRate(this::broadcastKeepAlive, 0L, 5L, TimeUnit.SECONDS); executor.scheduleAtFixedRate(this::broadcastKeepAlive, 0L, 5L, TimeUnit.SECONDS);
@ -89,21 +69,6 @@ public final class LimboServer {
Logger.info("Server started on %s", config.getAddress()); Logger.info("Server started on %s", config.getAddress());
} }
private void initInGameData(){
if (config.isUseJoinMessage()){
joinMessage = new PacketChatMessage();
joinMessage.setJsonData(config.getJoinMessage());
joinMessage.setPosition(PacketChatMessage.Position.CHAT);
joinMessage.setSender(UUID.randomUUID());
}
if (config.isUseBossBar()){
joinBossBar = new PacketBossBar();
joinBossBar.setBossBar(config.getBossBar());
joinBossBar.setUuid(UUID.randomUUID());
}
}
private void broadcastKeepAlive(){ private void broadcastKeepAlive(){
connections.getAllConnections().forEach(ClientConnection::sendKeepAlive); connections.getAllConnections().forEach(ClientConnection::sendKeepAlive);
} }

View File

@ -1,42 +0,0 @@
package ru.nanit.limbo.util;
import io.netty.buffer.ByteBuf;
import ru.nanit.limbo.configuration.LimboConfig;
import ru.nanit.limbo.protocol.ByteMessage;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
public final class VelocityUtil {
private static byte[] secretKey;
private VelocityUtil(){}
public static void init(LimboConfig config){
secretKey = config.getInfoForwarding().getSecretKey();
}
public static boolean checkIntegrity(ByteMessage buf) {
byte[] signature = new byte[32];
buf.readBytes(signature);
byte[] data = new byte[buf.readableBytes()];
buf.getBytes(buf.readerIndex(), data);
try {
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(secretKey, "HmacSHA256"));
byte[] mySignature = mac.doFinal(data);
if (!MessageDigest.isEqual(signature, mySignature))
return false;
} catch (InvalidKeyException |java.security.NoSuchAlgorithmException e) {
throw new AssertionError(e);
}
int version = buf.readVarInt();
if (version != 1)
throw new IllegalStateException("Unsupported forwarding version " + version + ", wanted " + '\001');
return true;
}
}