diff --git a/.classpath b/.classpath new file mode 100644 index 0000000..af1430b --- /dev/null +++ b/.classpath @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.gitignore b/.gitignore index 60321c7..4835c74 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,4 @@ hs_err_pid* *.iml # Created by .ignore support plugin (hsz.mobi) +/target/ diff --git a/.project b/.project new file mode 100644 index 0000000..cecf7f0 --- /dev/null +++ b/.project @@ -0,0 +1,23 @@ + + + JRakLibPlus + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000..5b781ec --- /dev/null +++ b/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,3 @@ +eclipse.preferences.version=1 +encoding//src/main/java=UTF-8 +encoding//src/test/java=UTF-8 diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..714351a --- /dev/null +++ b/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,5 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/.settings/org.eclipse.m2e.core.prefs b/.settings/org.eclipse.m2e.core.prefs new file mode 100644 index 0000000..f897a7f --- /dev/null +++ b/.settings/org.eclipse.m2e.core.prefs @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/src/main/java/io/github/jython234/jraklibplus/nio/Buffer.java b/src/main/java/io/github/jython234/jraklibplus/nio/Buffer.java index 78cb0e4..a86d4a8 100644 --- a/src/main/java/io/github/jython234/jraklibplus/nio/Buffer.java +++ b/src/main/java/io/github/jython234/jraklibplus/nio/Buffer.java @@ -19,6 +19,7 @@ */ package io.github.jython234.jraklibplus.nio; +import io.github.jython234.jraklibplus.protocol.ConnectionType; import io.github.jython234.jraklibplus.util.SystemAddress; /** @@ -58,6 +59,8 @@ public interface Buffer { String getString(); SystemAddress getAddress(); + + ConnectionType getConnectionType(); boolean getBoolean(); @@ -76,6 +79,8 @@ public interface Buffer { void putString(String s); void putAddress(SystemAddress address); + + ConnectionType putConnectionType(); void putBoolean(boolean b); diff --git a/src/main/java/io/github/jython234/jraklibplus/nio/JavaByteBuffer.java b/src/main/java/io/github/jython234/jraklibplus/nio/JavaByteBuffer.java index b94a031..9f48422 100644 --- a/src/main/java/io/github/jython234/jraklibplus/nio/JavaByteBuffer.java +++ b/src/main/java/io/github/jython234/jraklibplus/nio/JavaByteBuffer.java @@ -19,10 +19,12 @@ */ package io.github.jython234.jraklibplus.nio; +import io.github.jython234.jraklibplus.protocol.ConnectionType; import io.github.jython234.jraklibplus.util.SystemAddress; import java.nio.ByteBuffer; import java.nio.ByteOrder; +import java.util.Arrays; import java.util.regex.Pattern; /** @@ -31,160 +33,181 @@ * @author jython234 */ public class JavaByteBuffer implements Buffer { - private ByteBuffer buffer; - - protected JavaByteBuffer(ByteBuffer buffer) { - this.buffer = buffer; - } - - public static JavaByteBuffer allocate(int size, ByteOrder order) { - ByteBuffer bb = ByteBuffer.allocate(size); - bb.order(order); - return new JavaByteBuffer(bb); - } - - public static JavaByteBuffer wrap(byte[] bytes, ByteOrder order) { - ByteBuffer bb = ByteBuffer.wrap(bytes); - bb.order(order); - return new JavaByteBuffer(bb); - } - - @Override - public byte[] get(int len) { - byte[] data = new byte[len]; - buffer.get(data); - return data; - } - - @Override - public void put(byte[] bytes) { - buffer.put(bytes); - } - - @Override - public byte getByte() { - return buffer.get(); - } - - @Override - public short getShort() { - return buffer.getShort(); - } - - @Override - public int getUnsignedShort() { - return buffer.getShort() & 0xFFFF; - } - - @Override - public int getLTriad() { - return (getByte() & 0xFF) | ((getByte() & 0xFF) << 8) | ((getByte() & 0x0F) << 16); - } - - @Override - public int getInt() { - return buffer.getInt(); - } - - @Override - public long getLong() { - return buffer.getLong(); - } - - @Override - public String getString() { - return new String(get(getUnsignedShort())); - } - - @Override - public SystemAddress getAddress() { - int version = getByte(); - if (version == 4) { - String address = ((~getByte()) & 0xff) + "." + ((~getByte()) & 0xff) + "." + ((~getByte()) & 0xff) + "." + ((~getByte()) & 0xff); - int port = getUnsignedShort(); - return new SystemAddress(address, port, version); - } else if (version == 6) { - //TODO: IPv6 Decode - throw new UnsupportedOperationException("Can't read IPv6 address: Not Implemented"); - } else { - throw new UnsupportedOperationException("Can't read IPv" + version + " address: unknown"); - } - } - - @Override - public boolean getBoolean() { - return getByte() > 0; - } - - @Override - public void putByte(byte b) { - buffer.put(b); - } - - @Override - public void putShort(short s) { - buffer.putShort(s); - } - - @Override - public void putUnsignedShort(int us) { - buffer.putShort((short) us); - } - - @Override - public void putLTriad(int t) { - byte b1, b2, b3; - b3 = (byte) (t & 0xFF); - b2 = (byte) ((t >> 8) & 0xFF); - b1 = (byte) ((t >> 16) & 0xFF); - put(new byte[]{b3, b2, b1}); - } - - @Override - public void putInt(int i) { - buffer.putInt(i); - } - - @Override - public void putLong(long l) { - buffer.putLong(l); - } - - @Override - public void putString(String s) { - putUnsignedShort(s.getBytes().length); - put(s.getBytes()); - } - - @Override - public void putAddress(SystemAddress address) { - if (address.getVersion() != 4) { - throw new UnsupportedOperationException("Can't put IPv" + address.getVersion() + ": not implemented"); - } - putByte((byte) address.getVersion()); - for (String part : address.getIpAddress().split(Pattern.quote("."))) { - putByte((byte) ((byte) ~(Integer.parseInt(part)) & 0xFF)); - } - putUnsignedShort(address.getPort()); - } - - @Override - public void putBoolean(boolean b) { - putByte((byte) (b ? 1 : 0)); - } - - @Override - public void skip(int len) { - buffer.position(buffer.position() + len); - } - - @Override - public byte[] toByteArray() { - return buffer.array(); - } - - @Override - public int getRemainingBytes() { - return buffer.remaining(); - } + private ByteBuffer buffer; + + protected JavaByteBuffer(ByteBuffer buffer) { + this.buffer = buffer; + } + + public static JavaByteBuffer allocate(int size, ByteOrder order) { + ByteBuffer bb = ByteBuffer.allocate(size); + bb.order(order); + return new JavaByteBuffer(bb); + } + + public static JavaByteBuffer wrap(byte[] bytes, ByteOrder order) { + ByteBuffer bb = ByteBuffer.wrap(bytes); + bb.order(order); + return new JavaByteBuffer(bb); + } + + @Override + public byte[] get(int len) { + byte[] data = new byte[len]; + buffer.get(data); + return data; + } + + @Override + public void put(byte[] bytes) { + buffer.put(bytes); + } + + @Override + public byte getByte() { + return buffer.get(); + } + + @Override + public short getShort() { + return buffer.getShort(); + } + + @Override + public int getUnsignedShort() { + return buffer.getShort() & 0xFFFF; + } + + @Override + public int getLTriad() { + return (getByte() & 0xFF) | ((getByte() & 0xFF) << 8) | ((getByte() & 0x0F) << 16); + } + + @Override + public int getInt() { + return buffer.getInt(); + } + + @Override + public long getLong() { + return buffer.getLong(); + } + + @Override + public String getString() { + return new String(get(getUnsignedShort())); + } + + @Override + public SystemAddress getAddress() { + int version = getByte(); + if (version == 4) { + String address = ((~getByte()) & 0xff) + "." + ((~getByte()) & 0xff) + "." + ((~getByte()) & 0xff) + "." + + ((~getByte()) & 0xff); + int port = getUnsignedShort(); + return new SystemAddress(address, port, version); + } else if (version == 6) { + // TODO: IPv6 Decode + throw new UnsupportedOperationException("Can't read IPv6 address: Not Implemented"); + } else { + throw new UnsupportedOperationException("Can't read IPv" + version + " address: unknown"); + } + } + + @Override + public ConnectionType getConnectionType() { + // We add an extra byte because we need to read the ID + if (getRemainingBytes() >= ConnectionType.MAGIC.length + 1) { + byte[] connectionMagicCheck = get(ConnectionType.MAGIC.length); + if (Arrays.equals(ConnectionType.MAGIC, connectionMagicCheck)) { + short id = (short) (getByte() & 0xff); + return ConnectionType.getType(id); + } + } + return ConnectionType.VANILLA; + } + + @Override + public boolean getBoolean() { + return getByte() > 0; + } + + @Override + public void putByte(byte b) { + buffer.put(b); + } + + @Override + public void putShort(short s) { + buffer.putShort(s); + } + + @Override + public void putUnsignedShort(int us) { + buffer.putShort((short) us); + } + + @Override + public void putLTriad(int t) { + byte b1, b2, b3; + b3 = (byte) (t & 0xFF); + b2 = (byte) ((t >> 8) & 0xFF); + b1 = (byte) ((t >> 16) & 0xFF); + put(new byte[] { b3, b2, b1 }); + } + + @Override + public void putInt(int i) { + buffer.putInt(i); + } + + @Override + public void putLong(long l) { + buffer.putLong(l); + } + + @Override + public void putString(String s) { + putUnsignedShort(s.getBytes().length); + put(s.getBytes()); + } + + @Override + public void putAddress(SystemAddress address) { + if (address.getVersion() != 4) { + throw new UnsupportedOperationException("Can't put IPv" + address.getVersion() + ": not implemented"); + } + putByte((byte) address.getVersion()); + for (String part : address.getIpAddress().split(Pattern.quote("."))) { + putByte((byte) ((byte) ~(Integer.parseInt(part)) & 0xFF)); + } + putUnsignedShort(address.getPort()); + } + + @Override + public ConnectionType putConnectionType() { + put(ConnectionType.MAGIC); + putByte((byte) ConnectionType.JRAKLIB_PLUS.getId()); + return ConnectionType.JRAKLIB_PLUS; + } + + @Override + public void putBoolean(boolean b) { + putByte((byte) (b ? 1 : 0)); + } + + @Override + public void skip(int len) { + buffer.position(buffer.position() + len); + } + + @Override + public byte[] toByteArray() { + return buffer.array(); + } + + @Override + public int getRemainingBytes() { + return buffer.remaining(); + } } diff --git a/src/main/java/io/github/jython234/jraklibplus/nio/NioBuffer.java b/src/main/java/io/github/jython234/jraklibplus/nio/NioBuffer.java index 7a491d3..98a8400 100644 --- a/src/main/java/io/github/jython234/jraklibplus/nio/NioBuffer.java +++ b/src/main/java/io/github/jython234/jraklibplus/nio/NioBuffer.java @@ -19,210 +19,240 @@ */ package io.github.jython234.jraklibplus.nio; -import io.github.jython234.jraklibplus.util.SystemAddress; - import java.nio.BufferUnderflowException; import java.nio.ByteBuffer; import java.nio.ByteOrder; +import java.util.Arrays; import java.util.regex.Pattern; +import io.github.jython234.jraklibplus.protocol.ConnectionType; +import io.github.jython234.jraklibplus.util.SystemAddress; + /** - * An implementation of a Buffer. This class uses java.nio.ByteBuffer to read and write - * RakNet types. WARNING: Do NOT share buffer over multiple threads! + * An implementation of a Buffer. This class uses java.nio.ByteBuffer to read + * and write RakNet types. WARNING: Do NOT share buffer over multiple threads! * * @author jython234 */ public class NioBuffer implements Buffer { - private byte[] buffer; - private ByteOrder order; - private int position; - - protected NioBuffer(byte[] buffer, ByteOrder order) { - this.buffer = buffer; - this.order = order; - } - - /** - * Allocates and returns a new instance of a NioBuffer. This buffer will expand if the data attempting to be - * put is greater than the size of the buffer. - * @param initalSize The inital size of the buffer, which may expand if needed. - * @param order The ByteOrder or endianness of the buffer. - * @return A new allocated NioBuffer - */ - public static NioBuffer allocateBuffer(int initalSize, ByteOrder order) { - return new NioBuffer(new byte[initalSize], order); - } - - /** - * Creates a new NioBuffer wrapped around a byte array. The Buffer will be ready for reading from the specified - * byte array. - * @param bytes The byte array to be wrapped around of. - * @param order The ByteOrder or endianness of the buffer. - * @return A new NioBuffer wrapped around the specified byte array. - */ - public static NioBuffer wrapBuffer(byte[] bytes, ByteOrder order) { - return new NioBuffer(bytes, order); - } - - @Override - public byte[] get(int len) { - if (getRemainingBytes() < len) { - throw new BufferUnderflowException(); - } - byte[] data = new byte[len]; - //int offset = position == 0 ? 0 : 1; - int offset = 0; - for (int i = 0; i < len; i++) { - data[i] = buffer[position + offset]; - offset++; - } - position = position + offset; - return data; - } - - @Override - public void put(byte[] bytes) { - if ((buffer.length - position) < bytes.length) { - byte[] data = buffer; - buffer = new byte[bytes.length + data.length]; - position = 0; - put(data); - put(bytes); - return; - } - //int offset = position == 0 ? 0 : 1; - int offset = 0; - for (int i = 0; i < bytes.length; i++) { - buffer[position + offset] = bytes[i]; - offset++; - } - position = position + offset; - } - - @Override - public byte getByte() { - return get(1)[0]; - } - - @Override - public short getShort() { - return ByteBuffer.wrap(get(2)).order(order).getShort(); - } - - @Override - public int getUnsignedShort() { - return ByteBuffer.wrap(get(2)).order(order).getShort() & 0xFFFF; - } - - @Override - public int getLTriad() { - return (getByte() & 0xFF) | ((getByte() & 0xFF) << 8) | ((getByte() & 0x0F) << 16); - } - - @Override - public int getInt() { - return ByteBuffer.wrap(get(4)).order(order).getInt(); - } - - @Override - public long getLong() { - return ByteBuffer.wrap(get(8)).order(order).getLong(); - } - - @Override - public String getString() { - return new String(get(getUnsignedShort())); - } - - @Override - public SystemAddress getAddress() { - int version = getByte(); - if (version == 4) { - String address = ((~getByte()) & 0xff) + "." + ((~getByte()) & 0xff) + "." + ((~getByte()) & 0xff) + "." + ((~getByte()) & 0xff); - int port = getUnsignedShort(); - return new SystemAddress(address, port, version); - } else if (version == 6) { - //TODO: IPv6 Decode - throw new UnsupportedOperationException("Can't read IPv6 address: Not Implemented"); - } else { - throw new UnsupportedOperationException("Can't read IPv" + version + " address: unknown"); - } - } - - @Override - public boolean getBoolean() { - return getByte() > 0; - } - - @Override - public void putByte(byte b) { - put(new byte[]{b}); - } - - @Override - public void putShort(short s) { - put(ByteBuffer.allocate(2).order(order).putShort(s).array()); - } - - @Override - public void putUnsignedShort(int us) { - put(ByteBuffer.allocate(2).order(order).putShort((short) us).array()); - } - - @Override - public void putLTriad(int t) { - byte b1, b2, b3; - b3 = (byte) (t & 0xFF); - b2 = (byte) ((t >> 8) & 0xFF); - b1 = (byte) ((t >> 16) & 0xFF); - put(new byte[]{b3, b2, b1}); - } - - @Override - public void putInt(int i) { - put(ByteBuffer.allocate(4).order(order).putInt(i).array()); - } - - @Override - public void putLong(long l) { - put(ByteBuffer.allocate(8).order(order).putLong(l).array()); - } - - @Override - public void putString(String s) { - putUnsignedShort(s.getBytes().length); - put(s.getBytes()); - } - - @Override - public void putAddress(SystemAddress address) { - if (address.getVersion() != 4) { - throw new UnsupportedOperationException("Can't put IPv" + address.getVersion() + ": not implemented"); - } - putByte((byte) address.getVersion()); - for (String part : address.getIpAddress().split(Pattern.quote("."))) { - putByte((byte) ((byte) ~(Integer.parseInt(part)) & 0xFF)); - } - putUnsignedShort(address.getPort()); - } - - @Override - public void putBoolean(boolean b) { - putByte((byte) (b ? 1 : 0)); - } - - @Override - public void skip(int len) { - position = position + len; - } - - @Override - public byte[] toByteArray() { - return buffer; - } - - @Override - public int getRemainingBytes() { - return buffer.length - position; - } + private byte[] buffer; + private ByteOrder order; + private int position; + + protected NioBuffer(byte[] buffer, ByteOrder order) { + this.buffer = buffer; + this.order = order; + } + + /** + * Allocates and returns a new instance of a NioBuffer. This buffer will + * expand if the data attempting to be put is greater than the size of the + * buffer. + * + * @param initalSize + * The inital size of the buffer, which may expand if needed. + * @param order + * The ByteOrder or endianness of the buffer. + * @return A new allocated NioBuffer + */ + public static NioBuffer allocateBuffer(int initalSize, ByteOrder order) { + return new NioBuffer(new byte[initalSize], order); + } + + /** + * Creates a new NioBuffer wrapped around a byte array. The Buffer will be + * ready for reading from the specified byte array. + * + * @param bytes + * The byte array to be wrapped around of. + * @param order + * The ByteOrder or endianness of the buffer. + * @return A new NioBuffer wrapped around the specified byte array. + */ + public static NioBuffer wrapBuffer(byte[] bytes, ByteOrder order) { + return new NioBuffer(bytes, order); + } + + @Override + public byte[] get(int len) { + if (getRemainingBytes() < len) { + throw new BufferUnderflowException(); + } + byte[] data = new byte[len]; + // int offset = position == 0 ? 0 : 1; + int offset = 0; + for (int i = 0; i < len; i++) { + data[i] = buffer[position + offset]; + offset++; + } + position = position + offset; + return data; + } + + @Override + public void put(byte[] bytes) { + if ((buffer.length - position) < bytes.length) { + byte[] data = buffer; + buffer = new byte[bytes.length + data.length]; + position = 0; + put(data); + put(bytes); + return; + } + // int offset = position == 0 ? 0 : 1; + int offset = 0; + for (int i = 0; i < bytes.length; i++) { + buffer[position + offset] = bytes[i]; + offset++; + } + position = position + offset; + } + + @Override + public byte getByte() { + return get(1)[0]; + } + + @Override + public short getShort() { + return ByteBuffer.wrap(get(2)).order(order).getShort(); + } + + @Override + public int getUnsignedShort() { + return ByteBuffer.wrap(get(2)).order(order).getShort() & 0xFFFF; + } + + @Override + public int getLTriad() { + return (getByte() & 0xFF) | ((getByte() & 0xFF) << 8) | ((getByte() & 0x0F) << 16); + } + + @Override + public int getInt() { + return ByteBuffer.wrap(get(4)).order(order).getInt(); + } + + @Override + public long getLong() { + return ByteBuffer.wrap(get(8)).order(order).getLong(); + } + + @Override + public String getString() { + return new String(get(getUnsignedShort())); + } + + @Override + public SystemAddress getAddress() { + int version = getByte(); + if (version == 4) { + String address = ((~getByte()) & 0xff) + "." + ((~getByte()) & 0xff) + "." + ((~getByte()) & 0xff) + "." + + ((~getByte()) & 0xff); + int port = getUnsignedShort(); + return new SystemAddress(address, port, version); + } else if (version == 6) { + // TODO: IPv6 Decode + throw new UnsupportedOperationException("Can't read IPv6 address: Not Implemented"); + } else { + throw new UnsupportedOperationException("Can't read IPv" + version + " address: unknown"); + } + } + + @Override + public ConnectionType getConnectionType() { + // We add an extra byte because we need to read the ID + if (getRemainingBytes() >= ConnectionType.MAGIC.length + 1) { + byte[] connectionMagicCheck = get(ConnectionType.MAGIC.length); + if (Arrays.equals(ConnectionType.MAGIC, connectionMagicCheck)) { + short id = (short) (getByte() & 0xff); + return ConnectionType.getType(id); + } + } + return ConnectionType.VANILLA; + } + + @Override + public boolean getBoolean() { + return getByte() > 0; + } + + @Override + public void putByte(byte b) { + put(new byte[] { b }); + } + + @Override + public void putShort(short s) { + put(ByteBuffer.allocate(2).order(order).putShort(s).array()); + } + + @Override + public void putUnsignedShort(int us) { + put(ByteBuffer.allocate(2).order(order).putShort((short) us).array()); + } + + @Override + public void putLTriad(int t) { + byte b1, b2, b3; + b3 = (byte) (t & 0xFF); + b2 = (byte) ((t >> 8) & 0xFF); + b1 = (byte) ((t >> 16) & 0xFF); + put(new byte[] { b3, b2, b1 }); + } + + @Override + public void putInt(int i) { + put(ByteBuffer.allocate(4).order(order).putInt(i).array()); + } + + @Override + public void putLong(long l) { + put(ByteBuffer.allocate(8).order(order).putLong(l).array()); + } + + @Override + public void putString(String s) { + putUnsignedShort(s.getBytes().length); + put(s.getBytes()); + } + + @Override + public void putAddress(SystemAddress address) { + if (address.getVersion() != 4) { + throw new UnsupportedOperationException("Can't put IPv" + address.getVersion() + ": not implemented"); + } + putByte((byte) address.getVersion()); + for (String part : address.getIpAddress().split(Pattern.quote("."))) { + putByte((byte) ((byte) ~(Integer.parseInt(part)) & 0xFF)); + } + putUnsignedShort(address.getPort()); + } + + @Override + public ConnectionType putConnectionType() { + put(ConnectionType.MAGIC); + putByte((byte) ConnectionType.JRAKLIB_PLUS.getId()); + return ConnectionType.JRAKLIB_PLUS; + } + + @Override + public void putBoolean(boolean b) { + putByte((byte) (b ? 1 : 0)); + } + + @Override + public void skip(int len) { + position = position + len; + } + + @Override + public byte[] toByteArray() { + return buffer; + } + + @Override + public int getRemainingBytes() { + return buffer.length - position; + } } diff --git a/src/main/java/io/github/jython234/jraklibplus/protocol/ConnectionType.java b/src/main/java/io/github/jython234/jraklibplus/protocol/ConnectionType.java new file mode 100644 index 0000000..1e68849 --- /dev/null +++ b/src/main/java/io/github/jython234/jraklibplus/protocol/ConnectionType.java @@ -0,0 +1,72 @@ +/* + * JRakLibPlus is not affiliated with Jenkins Software LLC or RakNet. + * This software is an enhanced port of RakLib https://github.com/PocketMine/RakLib. + + * This file is part of JRakLibPlus. + * + * JRakLibPlus is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * JRakLibPlus is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with JRakLibPlus. If not, see . + */ +package io.github.jython234.jraklibplus.protocol; + +import lombok.Getter; + +/** + * Used to signify which implementation of the RakNet protocol is being used by + * a connection. If you would like your implementation to be listed here, create + * an issue on the JRakNet repository with the tag "Connection type support". + * Keep in mind that this functionality has no guarantees to function + * completely, as it is completely dependent on the implementation to implement + * this feature. + * + * @author Trent "Whirvis" Summerlin + * @author jython234 + * @see https://github.com/JRakNet/JRakNet/issues/new + */ +public enum ConnectionType { + + VANILLA("Vanilla", null, 0x00), JRAKNET("JRakNet", "Java", 0x01), RAKLIB("RakLib", "PHP", 0x02), + JRAKLIB_PLUS("JRakLib+", "Java", 0x03), CRAKNET_PLUS_PLUS("CRakNet++", "C++", 0x04), + PYRAKNET("PyRakNet", "Python", 0x05), GORAKNET("GoRakNet", "Go", 0x06), LUARAKNET("LuaRakNet", "Lua", 0x07), + CRAKNET_SHARP("CRakNet#", "C#", 0x08), PHPRAKNET("PHPRakNet", "PHP", 0x09), CRAKNET("CRakNet", "C", 0x0A), + DRAKNET("DRakNet", "D", 0x0B), NODERAKNET("NodeRakNet", "Node.js", 0x0C), ASMRAKNET("ASMRakNet", "Assembly", 0x0D), + JUNGLETREE("JungleTree", "Java", 0x0E); + + // Connection type header magic + public static final byte[] MAGIC = new byte[] { (byte) 0x03, (byte) 0x08, (byte) 0x05, (byte) 0x0B, 0x43, + (byte) 0x54, (byte) 0x49 }; + + @Getter private final String name; + @Getter private final String language; + @Getter private final short id; + + private ConnectionType(String name, String language, int id) { + this.name = name; + this.language = language; + this.id = (short) id; + if (id < 0 || id > 255) { + throw new IllegalArgumentException("Invalid ID, must be in between 0-255"); + } + } + + public static ConnectionType getType(int id) { + for (ConnectionType type : ConnectionType.values()) { + if (type.id == id) { + return type; + } + } + return ConnectionType.VANILLA; + } + +} diff --git a/src/main/java/io/github/jython234/jraklibplus/protocol/raknet/ConnectedPingOpenConnectionsPacket.java b/src/main/java/io/github/jython234/jraklibplus/protocol/raknet/ConnectedPingOpenConnectionsPacket.java index 9a36251..eb90303 100644 --- a/src/main/java/io/github/jython234/jraklibplus/protocol/raknet/ConnectedPingOpenConnectionsPacket.java +++ b/src/main/java/io/github/jython234/jraklibplus/protocol/raknet/ConnectedPingOpenConnectionsPacket.java @@ -20,6 +20,7 @@ package io.github.jython234.jraklibplus.protocol.raknet; import io.github.jython234.jraklibplus.nio.Buffer; +import io.github.jython234.jraklibplus.protocol.ConnectionType; import io.github.jython234.jraklibplus.protocol.RakNetPacket; import static io.github.jython234.jraklibplus.JRakLibPlus.ID_CONNECTED_PING_OPEN_CONNECTIONS; @@ -32,27 +33,30 @@ */ public class ConnectedPingOpenConnectionsPacket extends RakNetPacket { - public long pingID; - - @Override - protected void _encode(Buffer buffer) { - buffer.putLong(pingID); - buffer.put(RAKNET_MAGIC); - } - - @Override - protected void _decode(Buffer buffer) { - pingID = buffer.getLong(); - //MAGIC - } - - @Override - public byte getPID() { - return ID_CONNECTED_PING_OPEN_CONNECTIONS; - } - - @Override - public int getSize() { - return 25; - } + public long pingID; + public ConnectionType connectionType; + + @Override + protected void _encode(Buffer buffer) { + buffer.putLong(pingID); + buffer.put(RAKNET_MAGIC); + connectionType = buffer.putConnectionType(); + } + + @Override + protected void _decode(Buffer buffer) { + pingID = buffer.getLong(); + buffer.skip(16); //MAGIC + connectionType = buffer.getConnectionType(); + } + + @Override + public byte getPID() { + return ID_CONNECTED_PING_OPEN_CONNECTIONS; + } + + @Override + public int getSize() { + return 25; + } } diff --git a/src/main/java/io/github/jython234/jraklibplus/protocol/raknet/OpenConnectionReply2Packet.java b/src/main/java/io/github/jython234/jraklibplus/protocol/raknet/OpenConnectionReply2Packet.java index f0e4591..0e8ed43 100644 --- a/src/main/java/io/github/jython234/jraklibplus/protocol/raknet/OpenConnectionReply2Packet.java +++ b/src/main/java/io/github/jython234/jraklibplus/protocol/raknet/OpenConnectionReply2Packet.java @@ -20,6 +20,7 @@ package io.github.jython234.jraklibplus.protocol.raknet; import io.github.jython234.jraklibplus.nio.Buffer; +import io.github.jython234.jraklibplus.protocol.ConnectionType; import io.github.jython234.jraklibplus.protocol.RakNetPacket; import io.github.jython234.jraklibplus.util.SystemAddress; @@ -39,6 +40,7 @@ public class OpenConnectionReply2Packet extends RakNetPacket { * uint16 (unsigned short) */ public int mtuSize; + public ConnectionType connectionType; @Override protected void _encode(Buffer buffer) { @@ -47,6 +49,7 @@ protected void _encode(Buffer buffer) { buffer.putAddress(clientAddress); buffer.putUnsignedShort(mtuSize); buffer.putByte((byte) 0); //security + connectionType = buffer.putConnectionType(); } @Override @@ -55,7 +58,8 @@ protected void _decode(Buffer buffer) { serverID = buffer.getLong(); clientAddress = buffer.getAddress(); mtuSize = buffer.getUnsignedShort(); - //security + buffer.skip(1); // security + connectionType = buffer.getConnectionType(); } @Override diff --git a/src/main/java/io/github/jython234/jraklibplus/protocol/raknet/OpenConnectionRequest2Packet.java b/src/main/java/io/github/jython234/jraklibplus/protocol/raknet/OpenConnectionRequest2Packet.java index 3131e57..dd0d4f4 100644 --- a/src/main/java/io/github/jython234/jraklibplus/protocol/raknet/OpenConnectionRequest2Packet.java +++ b/src/main/java/io/github/jython234/jraklibplus/protocol/raknet/OpenConnectionRequest2Packet.java @@ -20,6 +20,7 @@ package io.github.jython234.jraklibplus.protocol.raknet; import io.github.jython234.jraklibplus.nio.Buffer; +import io.github.jython234.jraklibplus.protocol.ConnectionType; import io.github.jython234.jraklibplus.protocol.RakNetPacket; import io.github.jython234.jraklibplus.util.SystemAddress; @@ -33,36 +34,39 @@ */ public class OpenConnectionRequest2Packet extends RakNetPacket { - public SystemAddress serverAddress; - /** - * uint16 (unsigned short) - */ - public int mtuSize; - public long clientID; + public SystemAddress serverAddress; + /** + * uint16 (unsigned short) + */ + public int mtuSize; + public long clientID; + public ConnectionType connectionType; - @Override - protected void _encode(Buffer buffer) { - buffer.put(RAKNET_MAGIC); - buffer.putAddress(serverAddress); - buffer.putUnsignedShort(mtuSize); - buffer.putLong(clientID); - } + @Override + protected void _encode(Buffer buffer) { + buffer.put(RAKNET_MAGIC); + buffer.putAddress(serverAddress); + buffer.putUnsignedShort(mtuSize); + buffer.putLong(clientID); + connectionType = buffer.putConnectionType(); + } - @Override - protected void _decode(Buffer buffer) { - buffer.skip(16); //MAGIC - serverAddress = buffer.getAddress(); - mtuSize = buffer.getUnsignedShort(); - clientID = buffer.getUnsignedShort(); - } + @Override + protected void _decode(Buffer buffer) { + buffer.skip(16); // MAGIC + serverAddress = buffer.getAddress(); + mtuSize = buffer.getUnsignedShort(); + clientID = buffer.getLong(); + connectionType = buffer.getConnectionType(); + } - @Override - public byte getPID() { - return ID_OPEN_CONNECTION_REQUEST_2; - } + @Override + public byte getPID() { + return ID_OPEN_CONNECTION_REQUEST_2; + } - @Override - public int getSize() { - return 34; - } + @Override + public int getSize() { + return 34; + } } diff --git a/src/main/java/io/github/jython234/jraklibplus/protocol/raknet/UnconnectedPongOpenConnectionsPacket.java b/src/main/java/io/github/jython234/jraklibplus/protocol/raknet/UnconnectedPongOpenConnectionsPacket.java index 1ec5889..6bc7df3 100644 --- a/src/main/java/io/github/jython234/jraklibplus/protocol/raknet/UnconnectedPongOpenConnectionsPacket.java +++ b/src/main/java/io/github/jython234/jraklibplus/protocol/raknet/UnconnectedPongOpenConnectionsPacket.java @@ -20,6 +20,7 @@ package io.github.jython234.jraklibplus.protocol.raknet; import io.github.jython234.jraklibplus.nio.Buffer; +import io.github.jython234.jraklibplus.protocol.ConnectionType; import io.github.jython234.jraklibplus.protocol.RakNetPacket; import static io.github.jython234.jraklibplus.JRakLibPlus.ID_UNCONNECTED_PONG_OPEN_CONNECTIONS; @@ -35,6 +36,7 @@ public class UnconnectedPongOpenConnectionsPacket extends RakNetPacket { public long pingID; public long serverID; public String identifier; + public ConnectionType connectionType; @Override protected void _encode(Buffer buffer) { @@ -42,6 +44,7 @@ protected void _encode(Buffer buffer) { buffer.putLong(serverID); buffer.put(RAKNET_MAGIC); buffer.putString(identifier); + connectionType = buffer.putConnectionType(); } @Override @@ -50,6 +53,7 @@ protected void _decode(Buffer buffer) { serverID = buffer.getLong(); buffer.skip(16); //MAGIC identifier = buffer.getString(); + connectionType = buffer.getConnectionType(); } @Override diff --git a/src/main/java/io/github/jython234/jraklibplus/server/Session.java b/src/main/java/io/github/jython234/jraklibplus/server/Session.java index 61451d7..e1c12ce 100644 --- a/src/main/java/io/github/jython234/jraklibplus/server/Session.java +++ b/src/main/java/io/github/jython234/jraklibplus/server/Session.java @@ -22,6 +22,7 @@ import io.github.jython234.jraklibplus.JRakLibPlus; import io.github.jython234.jraklibplus.nio.Buffer; import io.github.jython234.jraklibplus.nio.JavaByteBuffer; +import io.github.jython234.jraklibplus.protocol.ConnectionType; import io.github.jython234.jraklibplus.protocol.RakNetPacket; import io.github.jython234.jraklibplus.protocol.minecraft.*; import io.github.jython234.jraklibplus.protocol.raknet.*; @@ -52,6 +53,7 @@ public class Session { @Getter private int state; @Getter private int mtu; @Getter private long clientID; + @Getter private ConnectionType connectionType; @Getter private long timeLastPacketReceived; @Getter private int lastPing = -99; @@ -224,6 +226,8 @@ public void handlePacket(byte[] data) { this.disconnect("Incorrect MTU"); return; } + + this.connectionType = req2.connectionType; OpenConnectionReply2Packet reply2 = new OpenConnectionReply2Packet(); reply2.serverID = this.server.getServerID();