13
0
geforkt von Mirrors/Velocity

Fix a bunch of small issues, so that the proxy can establish a connection

This is still broken and has performance/bandwidth problems, which I will
fix very soon. For a first try, it's good enough.
Dieser Commit ist enthalten in:
Andrew Steinborn 2018-07-24 23:40:20 -04:00
Ursprung dd8557d367
Commit 32772d1e9b
8 geänderte Dateien mit 70 neuen und 58 gelöschten Zeilen

Datei anzeigen

@ -9,33 +9,27 @@ public enum ProtocolUtils { ;
private static final int DEFAULT_MAX_STRING_SIZE = 65536; // 64KiB
public static int readVarInt(ByteBuf buf) {
int numRead = 0;
int result = 0;
byte read;
do {
read = buf.readByte();
int value = (read & 0b01111111);
result |= (value << (7 * numRead));
numRead++;
if (numRead > 5) {
throw new RuntimeException("VarInt is too big");
}
} while ((read & 0b10000000) != 0);
return result;
int i = 0;
int j = 0;
while (true) {
int k = buf.readByte();
i |= (k & 0x7F) << j++ * 7;
if (j > 5) throw new RuntimeException("VarInt too big");
if ((k & 0x80) != 128) break;
}
return i;
}
public static void writeVarInt(ByteBuf buf, int value) {
do {
byte temp = (byte)(value & 0b01111111);
// Note: >>> means that the sign bit is shifted with the rest of the number rather than being left alone
value >>>= 7;
if (value != 0) {
temp |= 0b10000000;
while (true) {
if ((value & 0xFFFFFF80) == 0) {
buf.writeByte(value);
return;
}
buf.writeByte(temp);
} while (value != 0);
buf.writeByte(value & 0x7F | 0x80);
value >>>= 7;
}
}
public static String readString(ByteBuf buf) {
@ -44,7 +38,7 @@ public enum ProtocolUtils { ;
public static String readString(ByteBuf buf, int cap) {
int length = readVarInt(buf);
Preconditions.checkArgument(length < cap, "Bad string size (got %s, maximum is %s)", length, cap);
Preconditions.checkArgument(length <= cap, "Bad string size (got %s, maximum is %s)", length, cap);
byte[] str = new byte[length];
buf.readBytes(str);
return new String(str, StandardCharsets.UTF_8);

Datei anzeigen

@ -32,7 +32,7 @@ public enum StateRegistry {
TO_CLIENT.register(0x00, Disconnect.class, Disconnect::new);
// Encryption Success will follow once Mojang auth/encryption is done
TO_CLIENT.register(0x02, ServerLoginSuccess.class, ServerLogin::new);
TO_CLIENT.register(0x02, ServerLoginSuccess.class, ServerLoginSuccess::new);
}
};

Datei anzeigen

@ -5,6 +5,7 @@ import io.minimum.minecraft.velocity.protocol.*;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.CorruptedFrameException;
import io.netty.handler.codec.MessageToMessageDecoder;
import java.util.List;
@ -35,7 +36,12 @@ public class MinecraftDecoder extends MessageToMessageDecoder<ByteBuf> {
msg.skipBytes(msg.readableBytes());
out.add(new PacketWrapper(null, slice));
} else {
packet.decode(msg, direction, protocolVersion);
try {
packet.decode(msg, direction, protocolVersion);
} catch (Exception e) {
throw new CorruptedFrameException("Error decoding " + packet.getClass() + " Direction " + direction
+ " Protocol " + protocolVersion + " State " + state + " ID " + Integer.toHexString(packetId), e);
}
out.add(new PacketWrapper(packet, slice));
}
}

Datei anzeigen

@ -55,17 +55,17 @@ public class Handshake implements MinecraftPacket {
@Override
public void decode(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) {
protocolVersion = ProtocolUtils.readVarInt(buf);
serverAddress = ProtocolUtils.readString(buf, 255);
port = buf.readUnsignedShort();
nextStatus = ProtocolUtils.readVarInt(buf);
this.protocolVersion = ProtocolUtils.readVarInt(buf);
this.serverAddress = ProtocolUtils.readString(buf, 255);
this.port = buf.readUnsignedShort();
this.nextStatus = ProtocolUtils.readVarInt(buf);
}
@Override
public void encode(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) {
ProtocolUtils.writeVarInt(buf, protocolVersion);
ProtocolUtils.writeString(buf, serverAddress);
buf.writeShort(port);
ProtocolUtils.writeVarInt(buf, nextStatus);
ProtocolUtils.writeVarInt(buf, this.protocolVersion);
ProtocolUtils.writeString(buf, this.serverAddress);
buf.writeShort(this.port);
ProtocolUtils.writeVarInt(buf, this.nextStatus);
}
}

Datei anzeigen

@ -37,11 +37,14 @@ public class ConnectedPlayer {
public void handleConnectionException(Throwable throwable) {
String error = "Exception: " + throwable.getClass().getName() + ": " + throwable.getMessage();
Disconnect disconnect = new Disconnect();
disconnect.setReason(ComponentSerializers.JSON.serialize(TextComponent.of(error, TextColor.RED)));
handleConnectionException(disconnect);
}
public void handleConnectionException(Disconnect disconnect) {
if (connectedServer == null) {
// The player isn't yet connected to a server - we should disconnect them.
Disconnect disconnect = new Disconnect();
disconnect.setReason(ComponentSerializers.JSON.serialize(TextComponent.of(error, TextColor.RED)));
connection.closeWith(disconnect);
} else {
// TODO

Datei anzeigen

@ -1,10 +1,13 @@
package io.minimum.minecraft.velocity.proxy;
import com.google.common.base.Preconditions;
import io.minimum.minecraft.velocity.data.ServerInfo;
import io.minimum.minecraft.velocity.protocol.ProtocolConstants;
import io.minimum.minecraft.velocity.protocol.StateRegistry;
import io.minimum.minecraft.velocity.protocol.netty.MinecraftDecoder;
import io.minimum.minecraft.velocity.protocol.netty.MinecraftEncoder;
import io.minimum.minecraft.velocity.protocol.packets.Handshake;
import io.minimum.minecraft.velocity.protocol.packets.ServerLoginSuccess;
import io.minimum.minecraft.velocity.proxy.handler.HandshakeSessionHandler;
import io.minimum.minecraft.velocity.proxy.handler.LoginSessionHandler;
import io.minimum.minecraft.velocity.proxy.handler.StatusSessionHandler;
@ -13,6 +16,7 @@ import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.util.AttributeKey;
import java.net.InetSocketAddress;
import java.util.Optional;
public class InboundMinecraftConnection {
@ -82,7 +86,7 @@ public class InboundMinecraftConnection {
Preconditions.checkState(!closed, "Connection is closed.");
}
public void setStatus(StateRegistry state) {
private void setStatus(StateRegistry state) {
Preconditions.checkNotNull(state, "state");
this.state = state;
channel.pipeline().get(MinecraftEncoder.class).setState(state);
@ -100,4 +104,16 @@ public class InboundMinecraftConnection {
public Optional<ConnectedPlayer> getConnectedPlayer() {
return Optional.ofNullable(connectedPlayer);
}
public int getProtocolVersion() {
return handshake == null ? ProtocolConstants.MINECRAFT_1_12 : handshake.getProtocolVersion();
}
public void initiatePlay(ServerLoginSuccess success) {
setStatus(StateRegistry.PLAY);
ConnectedPlayer player = new ConnectedPlayer(success.getUsername(), success.getUuid(), this);
ServerInfo info = new ServerInfo("test", new InetSocketAddress("127.0.0.1", 25565));
ServerConnection connection = new ServerConnection(info, player, VelocityServer.getServer());
connection.connect();
}
}

Datei anzeigen

@ -2,7 +2,6 @@ package io.minimum.minecraft.velocity.proxy;
import io.minimum.minecraft.velocity.protocol.MinecraftPacket;
import io.minimum.minecraft.velocity.protocol.PacketWrapper;
import io.minimum.minecraft.velocity.protocol.ProtocolConstants;
import io.minimum.minecraft.velocity.protocol.StateRegistry;
import io.minimum.minecraft.velocity.data.ServerInfo;
import io.minimum.minecraft.velocity.protocol.netty.MinecraftDecoder;
@ -13,9 +12,6 @@ import io.minimum.minecraft.velocity.protocol.packets.Handshake;
import io.minimum.minecraft.velocity.protocol.packets.ServerLogin;
import io.minimum.minecraft.velocity.protocol.packets.ServerLoginSuccess;
import io.netty.channel.*;
import net.kyori.text.serializer.ComponentSerializers;
import java.io.IOException;
public class ServerConnection {
private Channel channel;
@ -55,7 +51,7 @@ public class ServerConnection {
// Initiate a handshake.
Handshake handshake = new Handshake();
handshake.setNextStatus(2); // login
handshake.setProtocolVersion(ProtocolConstants.MINECRAFT_1_12); // TODO: Expose client version
handshake.setProtocolVersion(proxyPlayer.getConnection().getProtocolVersion()); // TODO: Expose client version
handshake.setServerAddress(info.getAddress().getHostString());
handshake.setPort(info.getAddress().getPort());
ctx.writeAndFlush(handshake, ctx.voidPromise());
@ -77,6 +73,9 @@ public class ServerConnection {
case LOGIN:
onLogin(ctx, pw);
break;
case PLAY:
onPlay(ctx, pw);
break;
default:
throw new UnsupportedOperationException("Unsupported state " + registry);
}
@ -86,16 +85,23 @@ public class ServerConnection {
}
}
private void onPlay(ChannelHandlerContext ctx, PacketWrapper pw) {
proxyPlayer.getConnection().write(pw.getBuffer().retain());
}
private void onLogin(ChannelHandlerContext ctx, PacketWrapper wrapper) {
//System.out.println("FROM PROXIED SERVER -> " + wrapper.getPacket() + " / " + ByteBufUtil.hexDump(wrapper.getBuffer()));
MinecraftPacket packet = wrapper.getPacket();
if (packet instanceof Disconnect) {
Disconnect disconnect = (Disconnect) packet;
ctx.close();
proxyPlayer.handleConnectionException(new IOException("Disconnected from target: " + jsonToPlain(disconnect.getReason())));
proxyPlayer.handleConnectionException(disconnect);
}
if (packet instanceof ServerLoginSuccess) {
System.out.println("got it");
// the player has been logged on.
System.out.println("Player connected to remote server");
setRegistry(StateRegistry.PLAY);
}
}
}
@ -105,10 +111,4 @@ public class ServerConnection {
this.channel.pipeline().get(MinecraftEncoder.class).setState(registry);
this.channel.pipeline().get(MinecraftDecoder.class).setState(registry);
}
private static String jsonToPlain(String j) {
return ComponentSerializers.LEGACY.serialize(
ComponentSerializers.JSON.deserialize(j)
).replaceAll("\\u00A7[a-z0-9]", "");
}
}

Datei anzeigen

@ -3,7 +3,6 @@ package io.minimum.minecraft.velocity.proxy.handler;
import com.google.common.base.Preconditions;
import io.minimum.minecraft.velocity.data.ServerInfo;
import io.minimum.minecraft.velocity.protocol.MinecraftPacket;
import io.minimum.minecraft.velocity.protocol.StateRegistry;
import io.minimum.minecraft.velocity.protocol.packets.ServerLogin;
import io.minimum.minecraft.velocity.protocol.packets.ServerLoginSuccess;
import io.minimum.minecraft.velocity.proxy.*;
@ -30,13 +29,7 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
success.setUuid(generateOfflinePlayerUuid(username));
connection.write(success);
connection.setStatus(StateRegistry.PLAY);
ConnectedPlayer player = new ConnectedPlayer(username, generateOfflinePlayerUuid(username), connection);
ServerInfo info = new ServerInfo("test", new InetSocketAddress("127.0.0.1", 25565));
ServerConnection connection = new ServerConnection(info, player, VelocityServer.getServer());
connection.connect();
connection.initiatePlay(success);
}
private static UUID generateOfflinePlayerUuid(String username) {