diff --git a/api/src/main/java/us/myles/ViaVersion/api/PacketWrapper.java b/api/src/main/java/us/myles/ViaVersion/api/PacketWrapper.java index fddc80353..358938812 100644 --- a/api/src/main/java/us/myles/ViaVersion/api/PacketWrapper.java +++ b/api/src/main/java/us/myles/ViaVersion/api/PacketWrapper.java @@ -171,7 +171,9 @@ public class PacketWrapper { } else { Pair read = readableObjects.poll(); Type rtype = read.getKey(); - if (rtype.equals(type) || (type.getBaseClass().equals(rtype.getBaseClass()) && type.getOutputClass().equals(rtype.getOutputClass()))) { + if (rtype.equals(type) + || (type.getBaseClass().equals(rtype.getBaseClass()) + && type.getOutputClass().equals(rtype.getOutputClass()))) { return (T) read.getValue(); } else { if (rtype == Type.NOTHING) { @@ -202,7 +204,7 @@ public class PacketWrapper { } } } - packetValues.add(new Pair(type, value)); + packetValues.add(new Pair<>(type, value)); } /** @@ -229,7 +231,7 @@ public class PacketWrapper { packetValues.addAll(readableObjects); readableObjects.clear(); // If the buffer has readable bytes, copy them. - if (inputBuffer.readableBytes() > 0) { + if (inputBuffer.isReadable()) { passthrough(Type.REMAINING_BYTES); } } @@ -292,7 +294,7 @@ public class PacketWrapper { private void writeRemaining(ByteBuf output) { if (inputBuffer != null) { - output.writeBytes(inputBuffer, inputBuffer.readableBytes()); + output.writeBytes(inputBuffer); } } @@ -367,8 +369,12 @@ public class PacketWrapper { // Apply other protocols apply(direction, user().getProtocolInfo().getState(), index, protocols, reverse); ByteBuf output = inputBuffer == null ? user().getChannel().alloc().buffer() : inputBuffer.alloc().buffer(); - writeToBuffer(output); - return output; + try { + writeToBuffer(output); + return output.retain(); + } finally { + output.release(); + } } /** @@ -414,8 +420,12 @@ public class PacketWrapper { if (!isCancelled()) { // Send ByteBuf output = inputBuffer == null ? user().getChannel().alloc().buffer() : inputBuffer.alloc().buffer(); - writeToBuffer(output); - user().sendRawPacket(output); + try { + writeToBuffer(output); + user().sendRawPacket(output.retain()); + } finally { + output.release(); + } } } @@ -538,9 +548,13 @@ public class PacketWrapper { public void sendToServer() throws Exception { if (!isCancelled()) { ByteBuf output = inputBuffer == null ? user().getChannel().alloc().buffer() : inputBuffer.alloc().buffer(); - writeToBuffer(output); + try { + writeToBuffer(output); - user().sendRawPacketToServer(output, true); + user().sendRawPacketToServer(output.retain(), true); + } finally { + output.release(); + } } } diff --git a/api/src/main/java/us/myles/ViaVersion/api/data/UserConnection.java b/api/src/main/java/us/myles/ViaVersion/api/data/UserConnection.java index 3f6fc3528..b3c1adee7 100644 --- a/api/src/main/java/us/myles/ViaVersion/api/data/UserConnection.java +++ b/api/src/main/java/us/myles/ViaVersion/api/data/UserConnection.java @@ -22,6 +22,7 @@ */ package us.myles.ViaVersion.api.data; +import com.google.common.cache.CacheBuilder; import io.netty.buffer.ByteBuf; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; @@ -38,8 +39,12 @@ import us.myles.ViaVersion.protocols.base.ProtocolInfo; import us.myles.ViaVersion.util.ChatColorUtil; import us.myles.ViaVersion.util.PipelineUtil; +import java.util.Collections; import java.util.Map; +import java.util.Set; +import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; import java.util.function.Function; @@ -48,8 +53,11 @@ public class UserConnection { private final long id = IDS.incrementAndGet(); private final Channel channel; private final boolean clientSide; - Map storedObjects = new ConcurrentHashMap<>(); + Map, StoredObject> storedObjects = new ConcurrentHashMap<>(); private ProtocolInfo protocolInfo; + private final Set passthroughTokens = Collections.newSetFromMap(CacheBuilder.newBuilder() + .expireAfterWrite(10, TimeUnit.SECONDS) + .build().asMap()); private boolean active = true; private boolean pendingDisconnect; private Object lastPacket; @@ -285,9 +293,9 @@ public class UserConnection { .getPreviousContext(Via.getManager().getInjector().getDecoderName(), channel.pipeline()); try { Type.VAR_INT.writePrimitive(buf, PacketWrapper.PASSTHROUGH_ID); - } catch (Exception e) { - // Should not happen - Via.getPlatform().getLogger().warning("Type.VAR_INT.write thrown an exception: " + e); + Type.UUID.write(buf, generatePassthroughToken()); + } catch (Exception shouldNotHappen) { + throw new RuntimeException(shouldNotHappen); } buf.writeBytes(packet); Runnable act = () -> { @@ -418,7 +426,12 @@ public class UserConnection { private void transform(ByteBuf buf, Direction direction, Function cancelSupplier) throws Exception { int id = Type.VAR_INT.readPrimitive(buf); - if (id == PacketWrapper.PASSTHROUGH_ID) return; + if (id == PacketWrapper.PASSTHROUGH_ID) { + if (!passthroughTokens.remove(Type.UUID.read(buf))) { + throw new IllegalArgumentException("Invalid token"); + } + return; + } PacketWrapper wrapper = new PacketWrapper(id, buf, this); try { @@ -459,7 +472,7 @@ public class UserConnection { } } - public Map getStoredObjects() { + public Map, StoredObject> getStoredObjects() { return storedObjects; } @@ -564,4 +577,10 @@ public class UserConnection { public boolean shouldApplyBlockProtocol() { return !clientSide; // Don't apply protocol blocking on client-side } + + public UUID generatePassthroughToken() { + UUID token = UUID.randomUUID(); + passthroughTokens.add(token); + return token; + } } diff --git a/api/src/main/java/us/myles/ViaVersion/api/type/Type.java b/api/src/main/java/us/myles/ViaVersion/api/type/Type.java index d5dcb17e8..96c4e0dcf 100644 --- a/api/src/main/java/us/myles/ViaVersion/api/type/Type.java +++ b/api/src/main/java/us/myles/ViaVersion/api/type/Type.java @@ -31,27 +31,7 @@ import us.myles.ViaVersion.api.minecraft.Position; import us.myles.ViaVersion.api.minecraft.Vector; import us.myles.ViaVersion.api.minecraft.VillagerData; import us.myles.ViaVersion.api.minecraft.item.Item; -import us.myles.ViaVersion.api.type.types.ArrayType; -import us.myles.ViaVersion.api.type.types.BooleanType; -import us.myles.ViaVersion.api.type.types.ByteArrayType; -import us.myles.ViaVersion.api.type.types.ByteType; -import us.myles.ViaVersion.api.type.types.ComponentType; -import us.myles.ViaVersion.api.type.types.DoubleType; -import us.myles.ViaVersion.api.type.types.FloatType; -import us.myles.ViaVersion.api.type.types.IntType; -import us.myles.ViaVersion.api.type.types.LongArrayType; -import us.myles.ViaVersion.api.type.types.LongType; -import us.myles.ViaVersion.api.type.types.RemainingBytesType; -import us.myles.ViaVersion.api.type.types.ShortType; -import us.myles.ViaVersion.api.type.types.StringType; -import us.myles.ViaVersion.api.type.types.UUIDIntArrayType; -import us.myles.ViaVersion.api.type.types.UUIDType; -import us.myles.ViaVersion.api.type.types.UnsignedByteType; -import us.myles.ViaVersion.api.type.types.UnsignedShortType; -import us.myles.ViaVersion.api.type.types.VarIntArrayType; -import us.myles.ViaVersion.api.type.types.VarIntType; -import us.myles.ViaVersion.api.type.types.VarLongType; -import us.myles.ViaVersion.api.type.types.VoidType; +import us.myles.ViaVersion.api.type.types.*; import us.myles.ViaVersion.api.type.types.minecraft.BlockChangeRecordType; import us.myles.ViaVersion.api.type.types.minecraft.EulerAngleType; import us.myles.ViaVersion.api.type.types.minecraft.FlatItemArrayType; @@ -83,7 +63,7 @@ public abstract class Type implements ByteBufReader, ByteBufWriter { @Deprecated public static final Type BYTE_ARRAY = new ArrayType<>(Type.BYTE); public static final Type BYTE_ARRAY_PRIMITIVE = new ByteArrayType(); - + public static final Type SHORT_BYTE_ARRAY = new ShortByteArrayType(); public static final Type REMAINING_BYTES = new RemainingBytesType(); public static final Type UNSIGNED_BYTE = new UnsignedByteType(); diff --git a/api/src/main/java/us/myles/ViaVersion/api/type/types/ShortByteArrayType.java b/api/src/main/java/us/myles/ViaVersion/api/type/types/ShortByteArrayType.java new file mode 100644 index 000000000..0caec7639 --- /dev/null +++ b/api/src/main/java/us/myles/ViaVersion/api/type/types/ShortByteArrayType.java @@ -0,0 +1,26 @@ +package us.myles.ViaVersion.api.type.types; + +import io.netty.buffer.ByteBuf; +import us.myles.ViaVersion.api.type.Type; + +/** + * Byte array with a short prefix, used in 1.7 + */ +public class ShortByteArrayType extends Type { + public ShortByteArrayType() { + super(byte[].class); + } + + @Override + public void write(ByteBuf buffer, byte[] object) throws Exception { + buffer.writeShort(object.length); + buffer.writeBytes(object); + } + + @Override + public byte[] read(ByteBuf buffer) throws Exception { + byte[] array = new byte[buffer.readShort()]; + buffer.readBytes(array); + return array; + } +}