// Path: dragonite-proxy/src/main/java/com/vecsight/dragonite/proxy/exception/IncorrectHeaderException.java
// public class IncorrectHeaderException extends Exception {
// 
//     public IncorrectHeaderException(final String msg) {
//         super(msg);
//     }
// 
// }
// 
// Path: dragonite-proxy/src/main/java/com/vecsight/dragonite/proxy/header/AddressType.java
// public enum AddressType {
//     IPv4((byte) 0),
//     IPv6((byte) 1),
//     DOMAIN((byte) 2);
// 
//     private final byte value;
// 
//     AddressType(final byte value) {
//         this.value = value;
//     }
// 
//     public byte getValue() {
//         return value;
//     }
// 
//     private static final AddressType[] types = AddressType.values();
// 
//     public static AddressType fromByte(final byte type) {
//         try {
//             return types[type];
//         } catch (final ArrayIndexOutOfBoundsException e) {
//             throw new IllegalArgumentException("Type byte " + type + " not found");
//         }
//     }
// }
// 
// Path: dragonite-utils/src/main/java/com/vecsight/dragonite/utils/binary/BinaryReader.java
// public class BinaryReader {
// 
//     private final ByteBuffer byteBuffer;
// 
//     public BinaryReader(final byte[] bytes) {
//         byteBuffer = ByteBuffer.wrap(bytes);
//     }
// 
//     public byte getSignedByte() {
//         return byteBuffer.get();
//     }
// 
//     public short getUnsignedByte() {
//         return (short) (byteBuffer.get() & (short) 0xff);
//     }
// 
//     public short getSignedShort() {
//         return byteBuffer.getShort();
//     }
// 
//     public int getUnsignedShort() {
//         return byteBuffer.getShort() & 0xffff;
//     }
// 
//     public int getSignedInt() {
//         return byteBuffer.getInt();
//     }
// 
//     public long getUnsignedInt() {
//         return (long) byteBuffer.getInt() & 0xffffffffL;
//     }
// 
//     public void getBytes(final byte[] bytes) {
//         byteBuffer.get(bytes);
//     }
// 
//     public byte[] getBytesGroupWithByteLength() {
//         final short len = getUnsignedByte();
//         final byte[] bytes = new byte[len];
//         byteBuffer.get(bytes);
//         return bytes;
//     }
// 
//     public byte[] getBytesGroupWithShortLength() {
//         final int len = getUnsignedShort();
//         final byte[] bytes = new byte[len];
//         byteBuffer.get(bytes);
//         return bytes;
//     }
// 
//     public boolean getBoolean() {
//         return byteBuffer.get() != 0;
//     }
// 
//     public int remaining() {
//         return byteBuffer.remaining();
//     }
// 
// }
// 
// Path: dragonite-utils/src/main/java/com/vecsight/dragonite/utils/binary/BinaryWriter.java
// public class BinaryWriter {
// 
//     private final ByteBuffer byteBuffer;
// 
//     public BinaryWriter(final int capacity) {
//         byteBuffer = ByteBuffer.allocate(capacity);
//     }
// 
//     public BinaryWriter putSignedByte(final byte sb) {
//         byteBuffer.put(sb);
//         return this;
//     }
// 
//     public BinaryWriter putUnsignedByte(final short ub) {
//         byteBuffer.put((byte) (ub & 0xff));
//         return this;
//     }
// 
//     public BinaryWriter putSignedShort(final short ss) {
//         byteBuffer.putShort(ss);
//         return this;
//     }
// 
//     public BinaryWriter putUnsignedShort(final int us) {
//         byteBuffer.putShort((short) (us & 0xffff));
//         return this;
//     }
// 
//     public BinaryWriter putSignedInt(final int si) {
//         byteBuffer.putInt(si);
//         return this;
//     }
// 
//     public BinaryWriter putUnsignedInt(final long ui) {
//         byteBuffer.putInt((int) (ui & 0xffffffffL));
//         return this;
//     }
// 
//     public BinaryWriter putBytes(final byte[] bytes) {
//         byteBuffer.put(bytes);
//         return this;
//     }
// 
//     public BinaryWriter putBytesGroupWithByteLength(final byte[] bytes) {
//         putUnsignedByte((short) bytes.length);
//         putBytes(bytes);
//         return this;
//     }
// 
//     public BinaryWriter putBytesGroupWithShortLength(final byte[] bytes) {
//         putUnsignedShort(bytes.length);
//         putBytes(bytes);
//         return this;
//     }
// 
//     public BinaryWriter putBoolean(final boolean b) {
//         byteBuffer.put((byte) (b ? 1 : 0));
//         return this;
//     }
// 
//     public byte[] toBytes() {
//         return byteBuffer.array();
//     }
// 
// }


import com.vecsight.dragonite.proxy.exception.IncorrectHeaderException;
import com.vecsight.dragonite.proxy.header.AddressType;
import com.vecsight.dragonite.utils.binary.BinaryReader;
import com.vecsight.dragonite.utils.binary.BinaryWriter;
import java.nio.BufferUnderflowException;
        this.type = type;
        this.addr = addr;
        this.port = port;
        this.udpMode = udpMode;
    }

    public MuxConnectionRequestHeader(final byte[] header) throws IncorrectHeaderException {
        final BinaryReader reader = new BinaryReader(header);

        try {

            final byte rawType = reader.getSignedByte();

            try {
                type = AddressType.fromByte(rawType);
            } catch (final IllegalArgumentException e) {
                throw new IncorrectHeaderException("Invalid address type " + rawType);
            }

            switch (type) {
                case IPv4:
                    addr = new byte[4];
                    reader.getBytes(addr);
                    break;
                case IPv6:
                    addr = new byte[16];
                    reader.getBytes(addr);
                    break;
                case DOMAIN:
                    addr = reader.getBytesGroupWithByteLength();
// Path: dragonite-proxy/src/main/java/com/vecsight/dragonite/proxy/exception/IncorrectHeaderException.java
// public class IncorrectHeaderException extends Exception {
// 
//     public IncorrectHeaderException(final String msg) {
//         super(msg);
//     }
// 
// }
// 
// Path: dragonite-proxy/src/main/java/com/vecsight/dragonite/proxy/header/AddressType.java
// public enum AddressType {
//     IPv4((byte) 0),
//     IPv6((byte) 1),
//     DOMAIN((byte) 2);
// 
//     private final byte value;
// 
//     AddressType(final byte value) {
//         this.value = value;
//     }
// 
//     public byte getValue() {
//         return value;
//     }
// 
//     private static final AddressType[] types = AddressType.values();
// 
//     public static AddressType fromByte(final byte type) {
//         try {
//             return types[type];
//         } catch (final ArrayIndexOutOfBoundsException e) {
//             throw new IllegalArgumentException("Type byte " + type + " not found");
//         }
//     }
// }
// 
// Path: dragonite-utils/src/main/java/com/vecsight/dragonite/utils/binary/BinaryReader.java
// public class BinaryReader {
// 
//     private final ByteBuffer byteBuffer;
// 
//     public BinaryReader(final byte[] bytes) {
//         byteBuffer = ByteBuffer.wrap(bytes);
//     }
// 
//     public byte getSignedByte() {
//         return byteBuffer.get();
//     }
// 
//     public short getUnsignedByte() {
//         return (short) (byteBuffer.get() & (short) 0xff);
//     }
// 
//     public short getSignedShort() {
//         return byteBuffer.getShort();
//     }
// 
//     public int getUnsignedShort() {
//         return byteBuffer.getShort() & 0xffff;
//     }
// 
//     public int getSignedInt() {
//         return byteBuffer.getInt();
//     }
// 
//     public long getUnsignedInt() {
//         return (long) byteBuffer.getInt() & 0xffffffffL;
//     }
// 
//     public void getBytes(final byte[] bytes) {
//         byteBuffer.get(bytes);
//     }
// 
//     public byte[] getBytesGroupWithByteLength() {
//         final short len = getUnsignedByte();
//         final byte[] bytes = new byte[len];
//         byteBuffer.get(bytes);
//         return bytes;
//     }
// 
//     public byte[] getBytesGroupWithShortLength() {
//         final int len = getUnsignedShort();
//         final byte[] bytes = new byte[len];
//         byteBuffer.get(bytes);
//         return bytes;
//     }
// 
//     public boolean getBoolean() {
//         return byteBuffer.get() != 0;
//     }
// 
//     public int remaining() {
//         return byteBuffer.remaining();
//     }
// 
// }
// 
// Path: dragonite-utils/src/main/java/com/vecsight/dragonite/utils/binary/BinaryWriter.java
// public class BinaryWriter {
// 
//     private final ByteBuffer byteBuffer;
// 
//     public BinaryWriter(final int capacity) {
//         byteBuffer = ByteBuffer.allocate(capacity);
//     }
// 
//     public BinaryWriter putSignedByte(final byte sb) {
//         byteBuffer.put(sb);
//         return this;
//     }
// 
//     public BinaryWriter putUnsignedByte(final short ub) {
//         byteBuffer.put((byte) (ub & 0xff));
//         return this;
//     }
// 
//     public BinaryWriter putSignedShort(final short ss) {
//         byteBuffer.putShort(ss);
//         return this;
//     }
// 
//     public BinaryWriter putUnsignedShort(final int us) {
//         byteBuffer.putShort((short) (us & 0xffff));
//         return this;
//     }
// 
//     public BinaryWriter putSignedInt(final int si) {
//         byteBuffer.putInt(si);
//         return this;
//     }
// 
//     public BinaryWriter putUnsignedInt(final long ui) {
//         byteBuffer.putInt((int) (ui & 0xffffffffL));
//         return this;
//     }
// 
//     public BinaryWriter putBytes(final byte[] bytes) {
//         byteBuffer.put(bytes);
//         return this;
//     }
// 
//     public BinaryWriter putBytesGroupWithByteLength(final byte[] bytes) {
//         putUnsignedByte((short) bytes.length);
//         putBytes(bytes);
//         return this;
//     }
// 
//     public BinaryWriter putBytesGroupWithShortLength(final byte[] bytes) {
//         putUnsignedShort(bytes.length);
//         putBytes(bytes);
//         return this;
//     }
// 
//     public BinaryWriter putBoolean(final boolean b) {
//         byteBuffer.put((byte) (b ? 1 : 0));
//         return this;
//     }
// 
//     public byte[] toBytes() {
//         return byteBuffer.array();
//     }
// 
// }


// Path: dragonite-proxy/src/main/java/com/vecsight/dragonite/proxy/header/mux/MuxConnectionRequestHeader.java
import com.vecsight.dragonite.proxy.exception.IncorrectHeaderException;
import com.vecsight.dragonite.proxy.header.AddressType;
import com.vecsight.dragonite.utils.binary.BinaryReader;
import com.vecsight.dragonite.utils.binary.BinaryWriter;
import java.nio.BufferUnderflowException;

        this.type = type;
        this.addr = addr;
        this.port = port;
        this.udpMode = udpMode;
    }

    public MuxConnectionRequestHeader(final byte[] header) throws IncorrectHeaderException {
        final BinaryReader reader = new BinaryReader(header);

        try {

            final byte rawType = reader.getSignedByte();

            try {
                type = AddressType.fromByte(rawType);
            } catch (final IllegalArgumentException e) {
                throw new IncorrectHeaderException("Invalid address type " + rawType);
            }

            switch (type) {
                case IPv4:
                    addr = new byte[4];
                    reader.getBytes(addr);
                    break;
                case IPv6:
                    addr = new byte[16];
                    reader.getBytes(addr);
                    break;
                case DOMAIN:
                    addr = reader.getBytesGroupWithByteLength();
                    break;