diff --git a/.classpath b/.classpath
index eae1a3d..542097f 100644
--- a/.classpath
+++ b/.classpath
@@ -5,5 +5,10 @@
+
+
+
+
+
diff --git a/lib/ClientHolocore-javadoc.jar b/lib/ClientHolocore-javadoc.jar
new file mode 100644
index 0000000..e3fed79
Binary files /dev/null and b/lib/ClientHolocore-javadoc.jar differ
diff --git a/lib/ClientHolocore.jar b/lib/ClientHolocore.jar
new file mode 100644
index 0000000..1d59255
Binary files /dev/null and b/lib/ClientHolocore.jar differ
diff --git a/src/com/projectswg/Connections.java b/src/com/projectswg/Connections.java
index cc00289..488041a 100644
--- a/src/com/projectswg/Connections.java
+++ b/src/com/projectswg/Connections.java
@@ -6,6 +6,8 @@ import java.util.concurrent.atomic.AtomicLong;
import network.packets.swg.ErrorMessage;
+import com.projectswg.connection.ServerConnectionChangedReason;
+import com.projectswg.connection.ServerConnectionStatus;
import com.projectswg.control.IntentManager;
import com.projectswg.control.Manager;
import com.projectswg.intents.ClientConnectionChangedIntent;
@@ -15,9 +17,7 @@ import com.projectswg.intents.ServerToClientPacketIntent;
import com.projectswg.networking.NetInterceptor.InterceptorProperties;
import com.projectswg.networking.client.ClientConnectionService;
import com.projectswg.networking.server.ServerConnectionService;
-import com.projectswg.networking.server.ServerConnectionChangedReason;
import com.projectswg.networking.soe.Disconnect.DisconnectReason;
-import com.projectswg.resources.ServerConnectionStatus;
import com.projectswg.services.PacketRecordingService;
import com.projectswg.utilities.Log;
import com.projectswg.utilities.ThreadUtilities;
diff --git a/src/com/projectswg/Forwarder.java b/src/com/projectswg/Forwarder.java
index 7c6724c..b4191aa 100644
--- a/src/com/projectswg/Forwarder.java
+++ b/src/com/projectswg/Forwarder.java
@@ -15,8 +15,9 @@ import javafx.scene.layout.GridPane;
import javafx.scene.paint.Color;
import javafx.scene.text.Text;
import javafx.stage.Stage;
+
import com.projectswg.Connections.ConnectionCallback;
-import com.projectswg.resources.ServerConnectionStatus;
+import com.projectswg.connection.ServerConnectionStatus;
import com.projectswg.utilities.Log;
public class Forwarder extends Application implements ConnectionCallback {
diff --git a/src/com/projectswg/intents/ServerConnectionChangedIntent.java b/src/com/projectswg/intents/ServerConnectionChangedIntent.java
index 6d611a5..071d94c 100644
--- a/src/com/projectswg/intents/ServerConnectionChangedIntent.java
+++ b/src/com/projectswg/intents/ServerConnectionChangedIntent.java
@@ -1,8 +1,8 @@
package com.projectswg.intents;
+import com.projectswg.connection.ServerConnectionChangedReason;
+import com.projectswg.connection.ServerConnectionStatus;
import com.projectswg.control.Intent;
-import com.projectswg.networking.server.ServerConnectionChangedReason;
-import com.projectswg.resources.ServerConnectionStatus;
public class ServerConnectionChangedIntent extends Intent {
diff --git a/src/com/projectswg/intents/ServerToClientPacketIntent.java b/src/com/projectswg/intents/ServerToClientPacketIntent.java
index 50501fc..4fdeafc 100644
--- a/src/com/projectswg/intents/ServerToClientPacketIntent.java
+++ b/src/com/projectswg/intents/ServerToClientPacketIntent.java
@@ -1,32 +1,30 @@
package com.projectswg.intents;
-import network.PacketType;
-
import com.projectswg.control.Intent;
public class ServerToClientPacketIntent extends Intent {
public static final String TYPE = "ServerToClientPacketIntent";
- private PacketType type;
+ private int crc;
private byte [] rawData;
- public ServerToClientPacketIntent(PacketType type, byte [] rawData) {
+ public ServerToClientPacketIntent(int crc, byte [] rawData) {
super(TYPE);
- setPacketType(type);
+ setCrc(crc);
setRawData(rawData);
}
- public PacketType getPacketType() {
- return type;
+ public int getCrc() {
+ return crc;
}
public byte [] getRawData() {
return rawData;
}
- public void setPacketType(PacketType type) {
- this.type = type;
+ public void setCrc(int crc) {
+ this.crc = crc;
}
public void setRawData(byte [] rawData) {
diff --git a/src/com/projectswg/networking/server/HolocoreProtocol.java b/src/com/projectswg/networking/server/HolocoreProtocol.java
deleted file mode 100644
index 4913eb6..0000000
--- a/src/com/projectswg/networking/server/HolocoreProtocol.java
+++ /dev/null
@@ -1,93 +0,0 @@
-package com.projectswg.networking.server;
-
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-import resources.network.NetBufferStream;
-
-import com.projectswg.networking.encryption.Compression;
-
-public class HolocoreProtocol {
-
- private static final byte [] EMPTY_PACKET = new byte[0];
-
- private final NetBufferStream inboundStream;
-
- public HolocoreProtocol() {
- this.inboundStream = new NetBufferStream();
- }
-
- public void reset() {
- inboundStream.reset();
- }
-
- public ByteBuffer assemble(byte [] raw) {
- int decompressedLength = raw.length;
- boolean compressed = raw.length >= 16;
- if (compressed) {
- byte [] compressedData = Compression.compress(raw);
- if (compressedData.length >= raw.length)
- compressed = false;
- else
- raw = compressedData;
- }
- ByteBuffer data = ByteBuffer.allocate(raw.length + 5).order(ByteOrder.LITTLE_ENDIAN);
- data.put(createBitmask(compressed, true));
- data.putShort((short) raw.length);
- data.putShort((short) decompressedLength);
- data.put(raw);
- data.flip();
- return data;
- }
-
- public boolean addToBuffer(ByteBuffer data) {
- synchronized (inboundStream) {
- inboundStream.write(data);
- inboundStream.mark();
- try {
- if (inboundStream.remaining() < 5)
- return false;
- inboundStream.getByte();
- short messageLength = inboundStream.getShort();
- inboundStream.getShort();
- if (inboundStream.remaining() < messageLength) {
- inboundStream.rewind();
- return false;
- }
- return true;
- } finally {
- inboundStream.rewind();
- }
- }
- }
-
- public byte [] disassemble() {
- synchronized (inboundStream) {
- inboundStream.mark();
- if (inboundStream.remaining() < 5) {
- inboundStream.rewind();
- return EMPTY_PACKET;
- }
- byte bitmask = inboundStream.getByte();
- short messageLength = inboundStream.getShort();
- short decompressedLength = inboundStream.getShort();
- if (inboundStream.remaining() < messageLength) {
- inboundStream.rewind();
- return EMPTY_PACKET;
- }
- byte [] message = inboundStream.getArray(messageLength);
- if ((bitmask & 1) != 0) // Compressed
- message = Compression.decompress(message, decompressedLength);
- inboundStream.compact();
- return message;
- }
- }
-
- private byte createBitmask(boolean compressed, boolean swg) {
- byte bitfield = 0;
- bitfield |= (compressed?1:0) << 0;
- bitfield |= (swg?1:0) << 1;
- return bitfield;
- }
-
-}
diff --git a/src/com/projectswg/networking/server/HolocoreSocket.java b/src/com/projectswg/networking/server/HolocoreSocket.java
deleted file mode 100644
index 80f4519..0000000
--- a/src/com/projectswg/networking/server/HolocoreSocket.java
+++ /dev/null
@@ -1,243 +0,0 @@
-package com.projectswg.networking.server;
-
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.nio.ByteBuffer;
-import java.nio.channels.AsynchronousCloseException;
-import java.nio.channels.SocketChannel;
-import java.util.Locale;
-import java.util.concurrent.atomic.AtomicReference;
-
-import network.PacketType;
-import network.packets.swg.holo.HoloConnectionStarted;
-import network.packets.swg.holo.HoloConnectionStopped;
-import network.packets.swg.holo.HoloSetProtocolVersion;
-import network.packets.swg.holo.HoloConnectionStopped.ConnectionStoppedReason;
-
-import com.projectswg.control.Assert;
-import com.projectswg.networking.server.SWGProtocol.RawPacket;
-import com.projectswg.resources.ServerConnectionStatus;
-import com.projectswg.utilities.Log;
-
-public class HolocoreSocket {
-
- private static final String PROTOCOL = "2016-04-13";
-
- private final Object socketMutex;
- private final ByteBuffer buffer;
- private final SWGProtocol swgProtocol;
- private final AtomicReference status;
- private SocketChannel socket;
- private StatusChangedCallback callback;
- private InetAddress addr;
- private int port;
-
- public HolocoreSocket(InetAddress addr, int port) {
- this.socketMutex = new Object();
- this.buffer = ByteBuffer.allocateDirect(128*1024);
- this.swgProtocol = new SWGProtocol();
- this.socket = null;
- this.status = new AtomicReference<>(ServerConnectionStatus.DISCONNECTED);
- this.callback = null;
- this.addr = addr;
- this.port = port;
- }
-
- public void setStatusChangedCallback(StatusChangedCallback callback) {
- this.callback = callback;
- }
-
- public void setRemoteAddress(InetAddress addr, int port) {
- this.addr = addr;
- this.port = port;
- }
-
- public InetSocketAddress getRemoteAddress() {
- return new InetSocketAddress(addr, port);
- }
-
- public ServerConnectionStatus getConnectionState() {
- return status.get();
- }
-
- public boolean isDisconnected() {
- return status.get() == ServerConnectionStatus.DISCONNECTED;
- }
-
- public boolean isConnecting() {
- return status.get() == ServerConnectionStatus.CONNECTING;
- }
-
- public boolean isConnected() {
- return status.get() == ServerConnectionStatus.CONNECTED;
- }
-
- public boolean connect() {
- synchronized (socketMutex) {
- Assert.test(isDisconnected());
- try {
- Log.out(this, "Connecting to %s at port %d", addr, port);
- swgProtocol.reset();
- socket = SocketChannel.open();
- updateStatus(ServerConnectionStatus.CONNECTING, ServerConnectionChangedReason.NONE);
- socket.socket().setKeepAlive(true);
- socket.socket().setPerformancePreferences(0, 1, 2);
- socket.socket().setTrafficClass(0x10); // Low Delay bit
- socket.configureBlocking(true);
- socket.connect(new InetSocketAddress(addr, port));
- if (!socket.finishConnect())
- return false;
- waitForConnect();
- Log.out(this, "Connected to Server");
- return true;
- } catch (IOException e) {
- if (e instanceof AsynchronousCloseException) {
- disconnect(ServerConnectionChangedReason.SOCKET_CLOSED);
- } else if (e.getMessage() == null) {
- disconnect(ServerConnectionChangedReason.UNKNOWN);
- Log.err(this, e);
- } else {
- disconnect(getReason(e.getMessage()));
- }
- return false;
- }
- }
- }
-
- public boolean disconnect(ServerConnectionChangedReason reason) {
- synchronized (socketMutex) {
- if (isDisconnected())
- return true;
- Assert.notNull(socket);
- updateStatus(ServerConnectionStatus.DISCONNECTED, reason);
- Log.out(this, "Disconnected from server with reason %s", reason);
- try {
- if (socket.isOpen())
- socket.write(swgProtocol.assemble(new HoloConnectionStopped(ConnectionStoppedReason.APPLICATION).encode().array()));
- socket.close();
- socket = null;
- return true;
- } catch (IOException e) {
- Log.err(this, e);
- return false;
- }
- }
- }
-
- public boolean send(byte [] raw) {
- return sendRaw(swgProtocol.assemble(raw));
- }
-
- public RawPacket read() {
- RawPacket packet = null;
- do {
- packet = swgProtocol.disassemble();
- if (packet != null)
- return packet;
- readRaw(buffer);
- swgProtocol.addToBuffer(buffer);
- } while (!isDisconnected());
- return null;
- }
-
- private boolean sendRaw(ByteBuffer data) {
- if (isDisconnected()) {
- Log.err(this, "Cannot send! Not connected.");
- return false;
- }
- try {
- synchronized (socketMutex) {
- socket.write(data);
- }
- return true;
- } catch (IOException e) {
- Log.err(this, e);
- disconnect(ServerConnectionChangedReason.OTHER_SIDE_TERMINATED);
- }
- return false;
- }
-
- private boolean readRaw(ByteBuffer data) {
- try {
- data.position(0);
- data.limit(data.capacity());
- int n = socket.read(data);
- if (n < 0) {
- disconnect(ServerConnectionChangedReason.OTHER_SIDE_TERMINATED);
- } else {
- data.flip();
- return true;
- }
- } catch (Exception e) {
- if (e instanceof AsynchronousCloseException) {
- disconnect(ServerConnectionChangedReason.SOCKET_CLOSED);
- } else if (e.getMessage() != null) {
- disconnect(getReason(e.getMessage()));
- } else {
- disconnect(ServerConnectionChangedReason.UNKNOWN);
- Log.err(this, e);
- }
- }
- return false;
- }
-
- private void waitForConnect() {
- send(new HoloSetProtocolVersion(PROTOCOL).encode().array());
- while (isConnecting()) {
- RawPacket packet = read();
- if (packet == null)
- continue;
- handlePacket(packet.getPacketType(), packet.getData());
- }
- if (isConnected())
- send(new HoloConnectionStarted().encode().array());
- }
-
- private void handlePacket(PacketType type, byte [] raw) {
- if (type == PacketType.HOLO_CONNECTION_STARTED) {
- updateStatus(ServerConnectionStatus.CONNECTED, ServerConnectionChangedReason.NONE);
- } else if (type == PacketType.HOLO_CONNECTION_STOPPED) {
- HoloConnectionStopped packet = new HoloConnectionStopped();
- packet.decode(ByteBuffer.wrap(raw));
- switch (packet.getReason()) {
- case INVALID_PROTOCOL:
- disconnect(ServerConnectionChangedReason.INVALID_PROTOCOL);
- break;
- default:
- disconnect(ServerConnectionChangedReason.NONE);
- break;
- }
- }
- }
-
- private void updateStatus(ServerConnectionStatus status, ServerConnectionChangedReason reason) {
- ServerConnectionStatus old = this.status.getAndSet(status);
- Log.out(this, "Server Status: %s -> %s", old, status);
- if (old != status && callback != null)
- callback.onConnectionStatusChanged(old, status, reason);
- }
-
- private ServerConnectionChangedReason getReason(String message) {
- message = message.toLowerCase(Locale.US);
- if (message.contains("broken pipe"))
- return ServerConnectionChangedReason.BROKEN_PIPE;
- if (message.contains("connection reset"))
- return ServerConnectionChangedReason.CONNECTION_RESET;
- if (message.contains("connection refused"))
- return ServerConnectionChangedReason.CONNECTION_REFUSED;
- if (message.contains("address in use"))
- return ServerConnectionChangedReason.ADDR_IN_USE;
- if (message.contains("socket closed"))
- return ServerConnectionChangedReason.SOCKET_CLOSED;
- if (message.contains("no route to host"))
- return ServerConnectionChangedReason.NO_ROUTE_TO_HOST;
- Log.err(this, "Unknown reason: " + message);
- return ServerConnectionChangedReason.UNKNOWN;
- }
-
- public interface StatusChangedCallback {
- void onConnectionStatusChanged(ServerConnectionStatus oldStatus, ServerConnectionStatus newStatus, ServerConnectionChangedReason reason);
- }
-
-}
diff --git a/src/com/projectswg/networking/server/SWGProtocol.java b/src/com/projectswg/networking/server/SWGProtocol.java
deleted file mode 100644
index 8ae86e0..0000000
--- a/src/com/projectswg/networking/server/SWGProtocol.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package com.projectswg.networking.server;
-
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-import network.PacketType;
-
-public class SWGProtocol {
-
- private final HolocoreProtocol holocore;
-
- public SWGProtocol() {
- holocore = new HolocoreProtocol();
- }
-
- public void reset() {
- holocore.reset();
- }
-
- public ByteBuffer assemble(byte [] packet) {
- return holocore.assemble(packet);
- }
-
- public boolean addToBuffer(ByteBuffer network) {
- return holocore.addToBuffer(network);
- }
-
- public RawPacket disassemble() {
- byte [] packet = holocore.disassemble();
- if (packet.length < 6)
- return null;
- ByteBuffer data = ByteBuffer.wrap(packet).order(ByteOrder.LITTLE_ENDIAN);
- PacketType type = PacketType.fromCrc(data.getInt(2));
- return new RawPacket(type, packet);
- }
-
- public static class RawPacket {
-
- private final PacketType type;
- private final byte [] data;
-
- public RawPacket(PacketType type, byte [] data) {
- this.type = type;
- this.data = data;
- }
-
- public PacketType getPacketType() {
- return type;
- }
-
- public byte [] getData() {
- return data;
- }
-
- }
-
-}
diff --git a/src/com/projectswg/networking/server/ServerConnectionChangedReason.java b/src/com/projectswg/networking/server/ServerConnectionChangedReason.java
deleted file mode 100644
index 3b4c582..0000000
--- a/src/com/projectswg/networking/server/ServerConnectionChangedReason.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.projectswg.networking.server;
-
-public enum ServerConnectionChangedReason {
- NONE,
- CLIENT_DISCONNECT,
- SOCKET_CLOSED,
- INVALID_PROTOCOL,
- BROKEN_PIPE,
- CONNECTION_RESET,
- CONNECTION_REFUSED,
- ADDR_IN_USE,
- NO_ROUTE_TO_HOST,
- OTHER_SIDE_TERMINATED,
- UNKNOWN
-}
diff --git a/src/com/projectswg/networking/server/ServerConnectionService.java b/src/com/projectswg/networking/server/ServerConnectionService.java
index 85d6656..6a3310a 100644
--- a/src/com/projectswg/networking/server/ServerConnectionService.java
+++ b/src/com/projectswg/networking/server/ServerConnectionService.java
@@ -8,11 +8,13 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
-import network.PacketType;
import network.packets.swg.zone.HeartBeat;
import com.projectswg.concurrency.PswgBasicScheduledThread;
import com.projectswg.concurrency.PswgBasicThread;
+import com.projectswg.connection.HolocoreSocket;
+import com.projectswg.connection.ServerConnectionChangedReason;
+import com.projectswg.connection.packets.RawPacket;
import com.projectswg.control.Assert;
import com.projectswg.control.IntentManager;
import com.projectswg.control.Service;
@@ -20,7 +22,6 @@ import com.projectswg.intents.ClientConnectionChangedIntent;
import com.projectswg.intents.ClientToServerPacketIntent;
import com.projectswg.intents.ServerConnectionChangedIntent;
import com.projectswg.intents.ServerToClientPacketIntent;
-import com.projectswg.networking.server.SWGProtocol.RawPacket;
import com.projectswg.utilities.IntentChain;
import com.projectswg.utilities.Log;
import com.projectswg.utilities.ThreadUtilities;
@@ -151,10 +152,10 @@ public class ServerConnectionService extends Service {
}
Assert.test(connection.isConnected());
RawPacket packet = null;
- while ((packet = connection.read()) != null) {
- if (packet.getPacketType() == PacketType.HEART_BEAT_MESSAGE)
+ while ((packet = connection.receive()) != null) {
+ if (packet.getCrc() == HeartBeat.CRC)
lastHeartbeat.set(System.nanoTime());
- recvIntentChain.broadcastAfter(new ServerToClientPacketIntent(packet.getPacketType(), packet.getData()));
+ recvIntentChain.broadcastAfter(new ServerToClientPacketIntent(packet.getCrc(), packet.getData()));
}
}
} catch (Throwable t) {
diff --git a/src/com/projectswg/networking/server/ServerConnectionWrapper.java b/src/com/projectswg/networking/server/ServerConnectionWrapper.java
index 43b9817..7bbdf4d 100644
--- a/src/com/projectswg/networking/server/ServerConnectionWrapper.java
+++ b/src/com/projectswg/networking/server/ServerConnectionWrapper.java
@@ -2,14 +2,12 @@ package com.projectswg.networking.server;
import java.net.InetAddress;
-import network.PacketType;
-
+import com.projectswg.connection.ServerConnectionStatus;
import com.projectswg.control.IntentManager;
import com.projectswg.intents.ClientConnectionChangedIntent;
import com.projectswg.intents.ServerConnectionChangedIntent;
import com.projectswg.intents.ServerToClientPacketIntent;
import com.projectswg.resources.ClientConnectionStatus;
-import com.projectswg.resources.ServerConnectionStatus;
public class ServerConnectionWrapper {
@@ -58,12 +56,12 @@ public class ServerConnectionWrapper {
private void onServerData(ServerToClientPacketIntent i) {
if (callback != null)
- callback.onServerPacket(i.getPacketType(), i.getRawData());
+ callback.onServerPacket(i.getCrc(), i.getRawData());
}
public interface ConnectionCallback {
void onServerConnectionChanged(ServerConnectionStatus old, ServerConnectionStatus status);
- void onServerPacket(PacketType type, byte [] data);
+ void onServerPacket(int crc, byte [] data);
}
}
diff --git a/src/com/projectswg/resources/ServerConnectionStatus.java b/src/com/projectswg/resources/ServerConnectionStatus.java
deleted file mode 100644
index 2a72215..0000000
--- a/src/com/projectswg/resources/ServerConnectionStatus.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.projectswg.resources;
-
-public enum ServerConnectionStatus {
- CONNECTING,
- CONNECTED,
- DISCONNECTED
-}
diff --git a/src/com/projectswg/services/PacketRecordingService.java b/src/com/projectswg/services/PacketRecordingService.java
index fa99586..9349409 100644
--- a/src/com/projectswg/services/PacketRecordingService.java
+++ b/src/com/projectswg/services/PacketRecordingService.java
@@ -4,13 +4,13 @@ import java.io.File;
import java.io.IOException;
import java.net.InetSocketAddress;
+import com.projectswg.connection.ServerConnectionStatus;
import com.projectswg.control.Assert;
import com.projectswg.control.Service;
import com.projectswg.intents.ClientToServerPacketIntent;
import com.projectswg.intents.ServerConnectionChangedIntent;
import com.projectswg.intents.ServerToClientPacketIntent;
import com.projectswg.recording.PacketRecorder;
-import com.projectswg.resources.ServerConnectionStatus;
import com.projectswg.utilities.Log;
public class PacketRecordingService extends Service {