packets.lib.ByteQueue

Here are the examples of the java api packets.lib.ByteQueue taken from open source projects. By voting up you can indicate which examples are most useful and appropriate.

10 Examples 7

19 Source : EncryptionManager.java
with GNU General Public License v3.0
from mircokroon

public void streamToServer(ByteQueue bytes) throws IOException {
    // System.out.println("Writing bytes to server: " + bytes.size() + " :: " + bytes);
    streamTo(streamToServer, bytes, this::serverBoundEncrypt);
}

19 Source : PacketBuilder.java
with GNU General Public License v3.0
from mircokroon

public clreplaced PacketBuilder {

    ByteQueue bytes;

    public PacketBuilder(int packetId) {
        this.bytes = new ByteQueue();
        writeVarInt(packetId);
    }

    public PacketBuilder() {
        this.bytes = new ByteQueue();
    }

    public byte[] toArray() {
        return bytes.toArray();
    }

    public void copy(DataTypeProvider provider, NetworkType... types) {
        for (NetworkType type : types) {
            type.copy(provider, this);
        }
    }

    public static PacketBuilder constructClientMessage(String message, MessageTarget target) {
        return constructClientMessage(new Chat(message), target);
    }

    /**
     * Construct a message packet for the client.
     */
    public static PacketBuilder constructClientMessage(Chat message, MessageTarget target) {
        Protocol protocol = Config.versionReporter().getProtocol();
        PacketBuilder builder = new PacketBuilder(protocol.clientBound("message"));
        builder.writeString(message.toJson());
        builder.writeByte(target.getIdentifier());
        if (Config.versionReporter().isAtLeast1_16()) {
            builder.writeUUID(new UUID(0L, 0L));
        }
        return builder;
    }

    /**
     * Method to write a varInt to the given list. Based on: https://wiki.vg/Protocol
     * @param value the value to write
     */
    public void writeVarInt(int value) {
        writeVarInt(this.bytes, value);
    }

    /**
     * Method to write a varInt to the given list. Based on: https://wiki.vg/Protocol
     * @param value the value to write
     */
    private static void writeVarInt(ByteQueue destination, 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;
            }
            destination.insert(temp);
        } while (value != 0);
    }

    private static ByteQueue createVarInt(int value) {
        ByteQueue res = new ByteQueue(5);
        writeVarInt(res, value);
        return res;
    }

    /**
     * Method to write a string to the given list.
     * @param str   the string to write
     */
    public void writeString(String str) {
        final byte[][] stringBytes = { null };
        stringBytes[0] = str.getBytes(StandardCharsets.UTF_8);
        writeVarInt(stringBytes[0].length);
        writeByteArray(stringBytes[0]);
    }

    /**
     * Method to write a byte array to the given list.
     * @param arr the bytes to write
     */
    public void writeByteArray(byte[] arr) {
        for (byte b : arr) {
            bytes.insert(b);
        }
    }

    /**
     * Method to write a the packet length to the start of the given list. This is done by writing the varint to a
     * different ByteQueue first, as we need to know the size before we can prepend it.
     */
    private void prependPacketLength() {
        int len = bytes.size();
        ByteQueue r = new ByteQueue(5);
        writeVarInt(r, len);
        this.bytes.prepend(r);
    }

    public ByteQueue build() {
        prependPacketLength();
        return bytes;
    }

    /**
     * If we're building a packet and we are given a compressionManager, that means we need to compress the packet
     * if it's large enough. The compression manager does compressing, but we still need to prefix the size and let the
     * client know if it was actually compressed.
     */
    public ByteQueue build(CompressionManager compressionManager) {
        if (!compressionManager.isCompressionEnabled()) {
            return build();
        }
        byte[] original = bytes.toArray();
        byte[] compressed = compressionManager.compressPacket(original);
        // no compression happened
        if (compressed == original) {
            // without compression the prefix is packet length + 0 byte
            ByteQueue prefix = createVarInt(original.length + 1);
            prefix.insert((byte) 0);
            this.bytes.prepend(prefix);
        } else {
            // with compression we need to first prefix a varInt of the uncompressed data length
            ByteQueue dataLen = createVarInt(original.length);
            // ...and then prefix the length of the entire packet
            ByteQueue packetLen = createVarInt(dataLen.size() + compressed.length);
            byte[] res = new byte[compressed.length + dataLen.size() + packetLen.size()];
            System.arraycopy(packetLen.toArray(), 0, res, 0, packetLen.size());
            System.arraycopy(dataLen.toArray(), 0, res, packetLen.size(), dataLen.size());
            System.arraycopy(compressed, 0, res, packetLen.size() + dataLen.size(), compressed.length);
            return new ByteQueue(res);
        }
        return bytes;
    }

    /**
     * Write a short to the given byte list.
     * @param shortVal the value of the short
     */
    public void writeShort(int shortVal) {
        bytes.insert((byte) ((shortVal >>> 8) & 0xFF));
        bytes.insert((byte) ((shortVal) & 0xFF));
    }

    /**
     * Write an int, needs to split into 4 bytes in the correct order.
     */
    public void writeInt(int val) {
        byte[] bytes = new byte[4];
        bytes[3] = (byte) (val & 0xFF);
        bytes[2] = (byte) (val >> 8 & 0xFF);
        bytes[1] = (byte) (val >> 16 & 0xFF);
        bytes[0] = (byte) (val >> 24 & 0xFF);
        writeByteArray(bytes);
    }

    public void writeBoolean(boolean val) {
        bytes.insert((byte) (val ? 0x1 : 0x0));
    }

    /**
     * Writes an NBT tag. We need to wrap this in a NamedTag, as the named tag is not written itself.
     */
    public void writeNbt(SpecificTag nbt) {
        try {
            new NamedTag("", nbt).write(new DataOutputStream(new OutputStream() {

                @Override
                public void write(int b) {
                    bytes.insert((byte) b);
                }
            }));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void writeByte(byte b) {
        bytes.insert(b);
    }

    public void writeUUID(UUID uuid) {
        writeLong(uuid.getLower());
        writeLong(uuid.getUpper());
    }

    public void writeLong(long val) {
        byte[] bytes = new byte[8];
        bytes[7] = (byte) (val & 0xFF);
        bytes[6] = (byte) (val >> 8 & 0xFF);
        bytes[5] = (byte) (val >> 16 & 0xFF);
        bytes[4] = (byte) (val >> 24 & 0xFF);
        bytes[3] = (byte) (val >> 32 & 0xFF);
        bytes[2] = (byte) (val >> 40 & 0xFF);
        bytes[1] = (byte) (val >> 48 & 0xFF);
        bytes[0] = (byte) (val >> 56 & 0xFF);
        writeByteArray(bytes);
    }

    public void writeVarIntArray(int[] arr) {
        for (int val : arr) {
            writeVarInt(val);
        }
    }

    public void writeLongArray(long[] arr) {
        for (long val : arr) {
            writeLong(val);
        }
    }

    public void writeStringArray(String[] arr) {
        for (String val : arr) {
            writeString(val);
        }
    }

    public void writeIntArray(int[] arr) {
        for (int i : arr) {
            writeInt(i);
        }
    }

    public void writeFloat(float val) {
        ByteBuffer buffer = ByteBuffer.allocate(Float.BYTES);
        buffer.putFloat(val);
        ((Buffer) buffer).flip();
        writeByteArray(buffer.array());
    }

    public void copyRemainder(DataTypeProvider provider) {
        writeByteArray(provider.readByteArray(provider.remaining()));
    }
}

19 Source : PacketBuilder.java
with GNU General Public License v3.0
from mircokroon

/**
 * Method to write a the packet length to the start of the given list. This is done by writing the varint to a
 * different ByteQueue first, as we need to know the size before we can prepend it.
 */
private void prependPacketLength() {
    int len = bytes.size();
    ByteQueue r = new ByteQueue(5);
    writeVarInt(r, len);
    this.bytes.prepend(r);
}

19 Source : PacketBuilder.java
with GNU General Public License v3.0
from mircokroon

private static ByteQueue createVarInt(int value) {
    ByteQueue res = new ByteQueue(5);
    writeVarInt(res, value);
    return res;
}

18 Source : PacketBuilderAndParserTest.java
with GNU General Public License v3.0
from mircokroon

/**
 * Get a DataTypeProvider built from the exiting packet builder.
 */
protected DataTypeProvider getParser() {
    ByteQueue built = builder.build();
    byte[] arr = new byte[built.size()];
    built.copyTo(arr);
    parser = new DataTypeProvider_1_14(arr);
    int length = parser.readVarInt();
    replacedertThat(length).isGreaterThan(0);
    int packetId = parser.readVarInt();
    return parser;
}

18 Source : EncryptionManager.java
with GNU General Public License v3.0
from mircokroon

/**
 * Method to stream a given queue of bytes to the client. Whenever this is called it also checks whether we have
 * any injected packets queued to be sent to the client.
 * @param bytes the bytes to stream
 */
public void streamToClient(ByteQueue bytes) throws IOException {
    streamTo(streamToClient, bytes, this::clientBoundEncrypt);
    // if we need to insert packets, send at most 100 at a time
    int limit = 100;
    while (!insertedPackets.isEmpty() && limit > 0) {
        limit--;
        streamTo(streamToClient, insertedPackets.remove(), this::clientBoundEncrypt);
    }
}

18 Source : PacketBuilder.java
with GNU General Public License v3.0
from mircokroon

/**
 * Method to write a varInt to the given list. Based on: https://wiki.vg/Protocol
 * @param value the value to write
 */
private static void writeVarInt(ByteQueue destination, 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;
        }
        destination.insert(temp);
    } while (value != 0);
}

16 Source : DataReader.java
with GNU General Public License v3.0
from mircokroon

/**
 * This clreplaced takes care of reading in bytes from the network steam and turning it into individual packets.
 */
public clreplaced DataReader {

    private static final int QUEUE_INIT_SIZE = 2 << 15 - 1;

    private ByteQueue queue;

    private ByteQueue currentPacket;

    private PacketHandler packetHandler;

    private final Supplier<Boolean> encryptionStatus;

    private final UnaryOperator<byte[]> decrypt;

    private final ByteConsumer transmit;

    private VarIntResult varIntPacketSize;

    /**
     * Initialise the reader. Gets a decryptor operator and transmitter method.
     * @param decrypt  the decryptor operator
     * @param transmit the transmit function
     */
    private DataReader(Supplier<Boolean> encryptionStatus, UnaryOperator<byte[]> decrypt, ByteConsumer transmit) {
        this.encryptionStatus = encryptionStatus;
        this.decrypt = decrypt;
        this.transmit = transmit;
        reset();
    }

    /**
     * Reset the reader in case the connection was lost.
     */
    public void reset() {
        queue = new ByteQueue(QUEUE_INIT_SIZE);
        currentPacket = new ByteQueue(QUEUE_INIT_SIZE);
        varIntPacketSize = new VarIntResult();
    }

    /**
     * Initialise a client-bound data reader.
     */
    public static DataReader clientBound(EncryptionManager manager) {
        return new DataReader(manager::isEncryptionEnabled, manager::clientBoundDecrypt, manager::streamToClient);
    }

    /**
     * Initialise a server-bound data reader.
     */
    public static DataReader serverBound(EncryptionManager manager) {
        return new DataReader(manager::isEncryptionEnabled, manager::serverBoundDecrypt, manager::streamToServer);
    }

    /**
     * Read a var int, uses the given hasNext and readNext methods to get the required bytes.
     */
    public static int readVarInt(Supplier<Boolean> hasNext, Supplier<Byte> readNext) {
        VarIntResult res = readVarInt(hasNext, readNext, new VarIntResult(false, 0, 0));
        if (!res.isComplete()) {
            throw new RuntimeException("Invalid VarInt found! Packet structure may have changed.");
        }
        return res.getResult();
    }

    /**
     * Read a full or partial varInt from the given reader method. As the connection will sometimes give us partial
     * varInts (with the rest having not yet arrived) we need to make sure we can handle partial results without the
     * connection becoming desynchronised. Adjusted from: https://wiki.vg/Protocol#Packet_format
     * @param res the object to the store the full or partial result in
     * @return the same object that it was given
     */
    public static VarIntResult readVarInt(Supplier<Boolean> hasNext, Supplier<Byte> readNext, VarIntResult res) {
        byte read;
        do {
            if (!hasNext.get()) {
                return res;
            }
            read = readNext.get();
            int value = (read & 0b01111111);
            res.addValue(value << (7 * res.numBytes()));
            res.addByteRead();
            if (res.numBytes() > 5) {
                throw new RuntimeException("VarInt is too big");
            }
        } while ((read & 0b10000000) != 0);
        res.setComplete(true);
        return res;
    }

    /**
     * Push data to this reader.
     * @param b      the bytes array containing the new data
     * @param amount the number of bytes to read from the array
     */
    public void pushData(byte[] b, int amount) throws IOException {
        if (amount == 0) {
            return;
        }
        if (encryptionStatus.get()) {
            decryptPacket(b, amount);
        } else {
            for (int i = 0; i < amount; i++) {
                queue.insert(b[i]);
            }
        }
        readPackets();
    }

    /**
     * If the packet is encrypted, decrypt it. Adds the decrypted bytes to the regular queue.
     * @param b      the encrypted bytes
     * @param amount the number of bytes to read from the given array
     */
    private void decryptPacket(byte[] b, int amount) {
        byte[] encrypted = b;
        if (b.length != amount) {
            encrypted = new byte[amount];
            System.arraycopy(b, 0, encrypted, 0, amount);
        }
        byte[] decrypted = decrypt.apply(encrypted);
        for (byte aDecrypted : decrypted) {
            queue.insert(aDecrypted);
        }
    }

    /**
     * Read packets from the byte queue. This method will first try to read a varInt indicating the upcoming packet's
     * size. Then, when the varInt is complete (may take several data transmissions), it will check if there is enough
     * bytes to complete the packet (this too may take several transmissions). After the packet is complete it will
     * be preplaceded to the packet builder which may decompress and read the data.
     * <p>
     * If the packet builder returns true, this means we will forward the packet. If the builder returns false, we will
     * dump the packet and move on. This will happen for the encryption related packets as sending the real one to the
     * server will prevent us from getting the encryption keys.
     */
    private void readPackets() throws IOException {
        int nextPacketSize;
        while (hasNext() && readPacketSize().isComplete()) {
            nextPacketSize = varIntPacketSize.getResult();
            // if we have enough bytes to parse the packet
            if (!hasBytes(nextPacketSize)) {
                return;
            }
            // parse the packet (including decompression)
            boolean forwardPacket = true;
            try {
                forwardPacket = getPacketHandler().handle(nextPacketSize);
            } catch (Exception ex) {
                ex.printStackTrace();
            }
            // check if the the packet length was correct
            int expectedLength = nextPacketSize + varIntPacketSize.numBytes();
            if (currentPacket.size() != expectedLength) {
                String msg = "Packet parsing may have been incorrect! Expected length: " + expectedLength + ". Used bytes: " + currentPacket.size();
                new IllegalStateException(msg).printStackTrace(System.err);
            }
            // forward the packet unless the packet builder decided swallowed it
            if (forwardPacket) {
                transmit.consume(currentPacket);
            }
            // clean up to prepare for next packet
            currentPacket.clear();
            varIntPacketSize.reset();
        }
    }

    /**
     * Check if we have more bytes in the queue right now.
     */
    private boolean hasNext() {
        return !queue.isEmpty();
    }

    /**
     * Read the packet size. Will continue reading with a previous result if that was not yet complete.
     */
    private VarIntResult readPacketSize() {
        if (!varIntPacketSize.isComplete()) {
            readVarInt(this::hasNext, this::readNext, varIntPacketSize);
        }
        return varIntPacketSize;
    }

    /**
     * Check if we have the given number of bytes. Used to check if the next package is complete.
     * @param amount the number of bytes required
     * @return true if we have sufficient bytes, otherwise false
     */
    private boolean hasBytes(int amount) {
        return amount <= queue.size();
    }

    private PacketHandler getPacketHandler() {
        return packetHandler;
    }

    public void setPacketHandler(PacketHandler packetHandler) {
        this.packetHandler = packetHandler;
        packetHandler.setReader(new DataProvider(this));
    }

    /**
     * Read a byte, also add it the current packet.
     */
    private byte readNext() {
        currentPacket.insert(queue.peek());
        return queue.remove();
    }

    /**
     * Read an array of bytes from the queue. Used to get all the bytes for a packet.
     * @param arrayLength the number of bytes to get
     * @return the full array
     */
    byte[] readByteArray(int arrayLength) {
        byte[] bytes = new byte[arrayLength];
        for (int i = 0; i < arrayLength; i++) {
            bytes[i] = readNext();
        }
        return bytes;
    }
}

16 Source : PacketBuilder.java
with GNU General Public License v3.0
from mircokroon

/**
 * If we're building a packet and we are given a compressionManager, that means we need to compress the packet
 * if it's large enough. The compression manager does compressing, but we still need to prefix the size and let the
 * client know if it was actually compressed.
 */
public ByteQueue build(CompressionManager compressionManager) {
    if (!compressionManager.isCompressionEnabled()) {
        return build();
    }
    byte[] original = bytes.toArray();
    byte[] compressed = compressionManager.compressPacket(original);
    // no compression happened
    if (compressed == original) {
        // without compression the prefix is packet length + 0 byte
        ByteQueue prefix = createVarInt(original.length + 1);
        prefix.insert((byte) 0);
        this.bytes.prepend(prefix);
    } else {
        // with compression we need to first prefix a varInt of the uncompressed data length
        ByteQueue dataLen = createVarInt(original.length);
        // ...and then prefix the length of the entire packet
        ByteQueue packetLen = createVarInt(dataLen.size() + compressed.length);
        byte[] res = new byte[compressed.length + dataLen.size() + packetLen.size()];
        System.arraycopy(packetLen.toArray(), 0, res, 0, packetLen.size());
        System.arraycopy(dataLen.toArray(), 0, res, packetLen.size(), dataLen.size());
        System.arraycopy(compressed, 0, res, packetLen.size() + dataLen.size(), compressed.length);
        return new ByteQueue(res);
    }
    return bytes;
}

15 Source : EncryptionManager.java
with GNU General Public License v3.0
from mircokroon

/**
 * Method to stream a queue of bytes to a given output stream. The stream will be encrypted if encryption has been
 * enabled.
 * @param stream  the stream to write to
 * @param bytes   the bytes to write
 * @param encrypt the encryption operator
 */
private void streamTo(OutputStream stream, ByteQueue bytes, UnaryOperator<byte[]> encrypt) throws IOException {
    byte[] b = bytes.toArray();
    byte[] encrypted = encrypt.apply(b);
    stream.write(encrypted, 0, encrypted.length);
    stream.flush();
}