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();