diff --git a/.classpath b/.classpath
index 8b7d01e..2ebdd55 100644
--- a/.classpath
+++ b/.classpath
@@ -1,11 +1,7 @@
-
-
-
-
-
+
diff --git a/.gitignore b/.gitignore
index e660fd9..a80544b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,3 @@
bin/
+/.gradle/
+/build/
diff --git a/Client Holocore b/Client Holocore
index be5b53b..41a5df8 160000
--- a/Client Holocore
+++ b/Client Holocore
@@ -1 +1 @@
-Subproject commit be5b53b4ea08260c945566938ab0f887b0d86ba9
+Subproject commit 41a5df892bf71bebad5085bc45d3b9e3107b5dfc
diff --git a/PSWGCommon b/PSWGCommon
index 016f219..8505a99 160000
--- a/PSWGCommon
+++ b/PSWGCommon
@@ -1 +1 @@
-Subproject commit 016f219e8092a55863118644a42e66d7253dcc39
+Subproject commit 8505a996c3758d5b1d4054d302474d4cd6979808
diff --git a/lib/Holocore.jar b/lib/Holocore.jar
deleted file mode 100644
index fd7e338..0000000
Binary files a/lib/Holocore.jar and /dev/null differ
diff --git a/src/com/projectswg/Connections.java b/src/com/projectswg/Connections.java
index 8b3106d..98ea2cd 100644
--- a/src/com/projectswg/Connections.java
+++ b/src/com/projectswg/Connections.java
@@ -8,6 +8,7 @@ import com.projectswg.common.concurrency.Delay;
import com.projectswg.common.control.IntentManager;
import com.projectswg.common.control.Manager;
import com.projectswg.common.debug.Log;
+import com.projectswg.common.network.packets.swg.ErrorMessage;
import com.projectswg.connection.ServerConnectionChangedReason;
import com.projectswg.connection.ServerConnectionStatus;
import com.projectswg.intents.ClientConnectionChangedIntent;
@@ -20,8 +21,6 @@ import com.projectswg.networking.server.ServerConnectionService;
import com.projectswg.networking.soe.Disconnect.DisconnectReason;
import com.projectswg.services.PacketRecordingService;
-import network.packets.swg.ErrorMessage;
-
public class Connections extends Manager {
public static final String VERSION = "0.9.8";
diff --git a/src/com/projectswg/networking/NetInterceptor.java b/src/com/projectswg/networking/NetInterceptor.java
index 21b6162..6c36778 100644
--- a/src/com/projectswg/networking/NetInterceptor.java
+++ b/src/com/projectswg/networking/NetInterceptor.java
@@ -1,11 +1,14 @@
package com.projectswg.networking;
-import com.projectswg.common.network.NetBuffer;
-import com.projectswg.networking.client.ClientData;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
-import network.packets.swg.login.LoginClientId;
-import network.packets.swg.login.LoginClusterStatus;
-import resources.Galaxy;
+import com.projectswg.common.data.encodables.galaxy.Galaxy;
+import com.projectswg.common.network.NetBuffer;
+import com.projectswg.common.network.packets.PacketType;
+import com.projectswg.common.network.packets.swg.login.LoginClientId;
+import com.projectswg.common.network.packets.swg.login.LoginClusterStatus;
+import com.projectswg.networking.client.ClientData;
public class NetInterceptor {
@@ -24,12 +27,12 @@ public class NetInterceptor {
public byte [] interceptClient(byte [] data) {
if (data.length < 6)
return data;
- NetBuffer buffer = NetBuffer.wrap(data);
- buffer.getShort();
- switch (buffer.getInt()) {
- case 0x41131F96: // LoginClientId
- return setAutoLogin(buffer);
- case 0x43FD1C22: // CmdSceneReady
+ ByteBuffer bb = ByteBuffer.wrap(data).order(ByteOrder.LITTLE_ENDIAN);
+ PacketType type = PacketType.fromCrc(bb.getInt(2));
+ switch (type) {
+ case LOGIN_CLIENT_ID:
+ return setAutoLogin(NetBuffer.wrap(bb));
+ case CMD_SCENE_READY:
clientData.setZoning(false);
return data;
default:
@@ -40,11 +43,11 @@ public class NetInterceptor {
public byte [] interceptServer(byte [] data) {
if (data.length < 6)
return data;
- NetBuffer buffer = NetBuffer.wrap(data);
- buffer.getShort();
- switch (buffer.getInt()) {
- case 0x3436AEB6: // LoginClusterStatus
- return getServerList(buffer);
+ ByteBuffer bb = ByteBuffer.wrap(data).order(ByteOrder.LITTLE_ENDIAN);
+ PacketType type = PacketType.fromCrc(bb.getInt(2));
+ switch (type) {
+ case LOGIN_CLUSTER_STATUS:
+ return getServerList(NetBuffer.wrap(bb));
default:
return data;
}
diff --git a/src/com/projectswg/networking/client/ClientConnectionService.java b/src/com/projectswg/networking/client/ClientConnectionService.java
index 9e39045..48a8a99 100644
--- a/src/com/projectswg/networking/client/ClientConnectionService.java
+++ b/src/com/projectswg/networking/client/ClientConnectionService.java
@@ -4,6 +4,8 @@ import com.projectswg.common.concurrency.Delay;
import com.projectswg.common.concurrency.PswgBasicScheduledThread;
import com.projectswg.common.control.Manager;
import com.projectswg.common.debug.Log;
+import com.projectswg.common.network.packets.SWGPacket;
+import com.projectswg.common.network.packets.swg.zone.HeartBeat;
import com.projectswg.intents.ServerToClientPacketIntent;
import com.projectswg.networking.NetInterceptor;
import com.projectswg.networking.NetInterceptor.InterceptorProperties;
@@ -15,9 +17,6 @@ import com.projectswg.networking.soe.Disconnect;
import com.projectswg.networking.soe.Disconnect.DisconnectReason;
import com.projectswg.resources.ClientConnectionStatus;
-import network.packets.swg.SWGPacket;
-import com.projectswg.common.network.packets.swg.zone.HeartBeat;
-
public class ClientConnectionService extends Manager implements ClientPacketSender {
private final NetInterceptor interceptor;
diff --git a/src/com/projectswg/networking/client/ClientPacketSender.java b/src/com/projectswg/networking/client/ClientPacketSender.java
index ee7bf55..00e81ad 100644
--- a/src/com/projectswg/networking/client/ClientPacketSender.java
+++ b/src/com/projectswg/networking/client/ClientPacketSender.java
@@ -1,9 +1,8 @@
package com.projectswg.networking.client;
+import com.projectswg.common.network.packets.SWGPacket;
import com.projectswg.networking.Packet;
-import network.packets.swg.SWGPacket;
-
public interface ClientPacketSender {
/** Adds the specified packets to a buffer to guarantee sending in-order */
diff --git a/src/com/projectswg/networking/client/sender/ClientPackager.java b/src/com/projectswg/networking/client/sender/ClientPackager.java
index 8688dcb..0837731 100644
--- a/src/com/projectswg/networking/client/sender/ClientPackager.java
+++ b/src/com/projectswg/networking/client/sender/ClientPackager.java
@@ -3,11 +3,14 @@ package com.projectswg.networking.client.sender;
import java.nio.ByteBuffer;
import java.util.ArrayDeque;
import java.util.Queue;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
import com.projectswg.common.concurrency.Delay;
import com.projectswg.common.concurrency.PswgBasicThread;
-import com.projectswg.common.concurrency.SmartLock;
-import com.projectswg.common.concurrency.SynchronizedQueue;
import com.projectswg.common.control.IntentManager;
import com.projectswg.common.debug.Assert;
import com.projectswg.intents.ClientConnectionChangedIntent;
@@ -21,133 +24,196 @@ import com.projectswg.resources.ClientConnectionStatus;
public class ClientPackager {
private final NetInterceptor interceptor;
- private final ClientData clientData;
private final ClientPacketResender packetResender;
- private final PswgBasicThread packagerThread;
- private final Queue inboundQueue;
- private final SmartLock inboundQueueLock;
- private final DataChannel channel;
- private int size;
+ private final PackagingWrapper packager;
public ClientPackager(NetInterceptor interceptor, ClientData clientData, ClientPacketSender sender) {
this.interceptor = interceptor;
- this.clientData = clientData;
- this.inboundQueue = new SynchronizedQueue<>(new ArrayDeque<>(128));
- this.inboundQueueLock = new SmartLock();
- this.packagerThread = new PswgBasicThread("packet-packager", () -> packagerRunnable());
this.packetResender = new ClientPacketResender(sender);
- this.channel = new DataChannel();
- reset();
+ this.packager = new PackagingWrapper(packetResender, clientData);
}
public void start(IntentManager intentManager) {
- Assert.test(inboundQueue.isEmpty(), "Inbound queue must be empty when starting!");
- packagerThread.start();
packetResender.start(intentManager);
+ packager.start();
intentManager.registerForIntent(ClientConnectionChangedIntent.class, ccci -> handleClientStatusChanged(ccci.getStatus()));
}
public void stop() {
+ packager.stop();
packetResender.stop();
- packagerThread.stop(true);
- packagerThread.awaitTermination(1000);
- inboundQueue.clear();
}
public void clear() {
- inboundQueue.clear();
+ packager.reset();
}
public void addToPackage(byte [] data) {
Assert.test(data.length > 0, "Array length must be greater than 0!");
- inboundQueue.add(data);
- inboundQueueLock.signal();
+ packager.add(interceptor.interceptServer(data));
}
private void handleClientStatusChanged(ClientConnectionStatus status) {
clear();
}
- private void packagerRunnable() {
- while (packagerThread.isRunning()) {
- if (handle(inboundQueue) > 0) {
- if (Delay.sleepMicro(25))
+ private static class PackagingWrapper {
+
+ private final AtomicBoolean running;
+ private final PswgBasicThread packagerThread;
+ private final ClientPacketResender packetResender;
+ private final Packager packager;
+ private final Queue inboundQueue;
+ private final Lock inboundQueueLock;
+ private final Condition inboundQueueCondition;
+
+ public PackagingWrapper(ClientPacketResender packetResender, ClientData clientData) {
+ this.running = new AtomicBoolean(false);
+ this.packagerThread = new PswgBasicThread("packet-packager", this::loop);
+ this.packetResender = packetResender;
+ this.packager = new Packager(clientData);
+ this.inboundQueue = new ArrayDeque<>(128);
+ this.inboundQueueLock = new ReentrantLock(false);
+ this.inboundQueueCondition = inboundQueueLock.newCondition();
+ }
+
+ public void start() {
+ running.set(true);
+ packagerThread.start();
+ }
+
+ public void stop() {
+ running.set(false);
+ packagerThread.stop(true);
+ packagerThread.awaitTermination(500);
+ }
+
+ public void reset() {
+ inboundQueue.clear();
+ }
+
+ public void add(byte [] packet) {
+ inboundQueueLock.lock();
+ try {
+ inboundQueue.add(packet);
+ inboundQueueCondition.signal();
+ } finally {
+ inboundQueueLock.unlock();
+ }
+ }
+
+ private void loop() {
+ Queue outboundQueue = new ArrayDeque<>(64);
+ while (running.get()) {
+ if (!waitForInbound())
break;
- } else {
+ processInbound(outboundQueue);
+ Delay.sleepMicro(25); // Accumulates some packets
+ }
+ }
+
+ /**
+ * Waits for the queue to be non-empty and acquires the lock
+ * @return TRUE if the lock is acquired and the queue is non-empty, FALSE otherwise
+ */
+ private boolean waitForInbound() {
+ inboundQueueLock.lock();
+ while (inboundQueue.isEmpty()) {
try {
- while (inboundQueue.isEmpty()) {
- inboundQueueLock.await();
- }
+ inboundQueueCondition.await();
} catch (InterruptedException e) {
+ running.set(false);
+ return false;
}
}
+ return true;
}
- }
-
- /**
- * Packages all packets in the queue appropriately
- * @param queue the queue of raw packets
- */
- private synchronized int handle(Queue queue) {
- byte [] packet;
- int packetSize;
- int packets = 0;
- Assert.test(size == 8, "Internal Packager size must equal 8 at start of loop!");
- Assert.test(channel.getPacketCount() == 0, "Internal Packager DataChannel must be empty at start of loop!");
- while (!queue.isEmpty()) {
- packet = interceptor.interceptServer(queue.poll());
- packetSize = getPacketLength(packet);
- if (size + packetSize >= 496) {
- handleDataChannelOverflow(packet, packetSize);
- } else {
- addToChannel(packet, packetSize);
+
+ private void processInbound(Queue outboundQueue) {
+ try {
+ packager.handle(inboundQueue, outboundQueue);
+ } finally {
+ inboundQueueLock.unlock();
+ }
+
+ while (!outboundQueue.isEmpty()) {
+ packetResender.add(outboundQueue.poll());
}
- packets++;
}
- sendDataChannel();
- return packets;
+
}
- private void handleDataChannelOverflow(byte [] packet, int packetSize) {
- sendDataChannel();
- if (packetSize >= 496) {
- sendFragmented(packet);
- return;
+ private static class Packager {
+
+ private final AtomicInteger size;
+ private final DataChannel channel;
+ private final ClientData clientData;
+
+ public Packager(ClientData clientData) {
+ this.size = new AtomicInteger(8);
+ this.channel = new DataChannel();
+ this.clientData = clientData;
}
- addToChannel(packet, packetSize);
- }
-
- private void addToChannel(byte [] packet, int packetSize) {
- channel.addPacket(packet);
- size += packetSize;
- }
-
- private void sendDataChannel() {
- if (channel.getPacketCount() == 0)
- return;
- channel.setSequence(clientData.getAndIncrementTxSequence());
- packetResender.add(channel.getSequence(), channel.encode().array());
- reset();
- }
-
- private void sendFragmented(byte [] packet) {
- Fragmented [] frags = Fragmented.encode(ByteBuffer.wrap(packet), clientData.getTxSequence());
- clientData.setTxSequence((short) (clientData.getTxSequence() + frags.length));
- for (Fragmented frag : frags) {
- packetResender.add(frag.getSequence(), frag.encode().array());
+
+ /**
+ * Processes the inbound queue, and then sends it to the outbound queue
+ * @param inboundQueue inbound queue from the server
+ * @param outboundQueue outbound queue to the client
+ */
+ public void handle(Queue inboundQueue, Queue outboundQueue) {
+ byte [] packet;
+ int packetSize;
+
+ while (!inboundQueue.isEmpty()) {
+ packet = inboundQueue.poll();
+ packetSize = getPacketLength(packet);
+
+ if (size.get() + packetSize >= 496) // overflowed previous packet
+ sendDataChannel(outboundQueue);
+
+ if (packetSize < 496) {
+ addToDataChannel(packet, packetSize);
+ } else {
+ sendFragmented(outboundQueue, packet);
+ }
+ }
+ sendDataChannel(outboundQueue);
}
- }
-
- private int getPacketLength(byte [] data) {
- int len = data.length;
- if (len >= 255)
- return len + 3;
- return len + 1;
- }
-
- private void reset() {
- channel.clearPackets();
- size = 8;
+
+ private void addToDataChannel(byte [] packet, int packetSize) {
+ channel.addPacket(packet);
+ size.getAndAdd(packetSize);
+ }
+
+ private void sendDataChannel(Queue outboundQueue) {
+ if (channel.getPacketCount() == 0)
+ return;
+
+ channel.setSequence(clientData.getAndIncrementTxSequence());
+ outboundQueue.add(new SequencedOutbound(channel.getSequence(), channel.encode().array()));
+ reset();
+ }
+
+ private void sendFragmented(Queue outboundQueue, byte [] packet) {
+ Fragmented [] frags = Fragmented.encode(ByteBuffer.wrap(packet), clientData.getTxSequence());
+ clientData.setTxSequence((short) (clientData.getTxSequence() + frags.length));
+ for (Fragmented frag : frags) {
+ outboundQueue.add(new SequencedOutbound(frag.getSequence(), frag.encode().array()));
+ }
+ }
+
+ private void reset() {
+ channel.clearPackets();
+ size.set(8);
+ }
+
+ private static int getPacketLength(byte [] data) {
+ int len = data.length;
+ if (len >= 255)
+ return len + 3;
+ return len + 1;
+ }
+
}
}
diff --git a/src/com/projectswg/networking/client/sender/ClientPacketResender.java b/src/com/projectswg/networking/client/sender/ClientPacketResender.java
index e406990..7728460 100644
--- a/src/com/projectswg/networking/client/sender/ClientPacketResender.java
+++ b/src/com/projectswg/networking/client/sender/ClientPacketResender.java
@@ -1,8 +1,11 @@
package com.projectswg.networking.client.sender;
-import java.util.ArrayList;
+import java.util.LinkedList;
import java.util.List;
-import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
import com.projectswg.common.concurrency.Delay;
import com.projectswg.common.concurrency.PswgBasicThread;
@@ -14,7 +17,6 @@ import com.projectswg.networking.Packet;
import com.projectswg.networking.client.ClientPacketSender;
import com.projectswg.networking.soe.Acknowledge;
import com.projectswg.networking.soe.OutOfOrder;
-import com.projectswg.networking.soe.SequencedPacket;
import com.projectswg.resources.ClientConnectionStatus;
/**
@@ -22,195 +24,229 @@ import com.projectswg.resources.ClientConnectionStatus;
*/
public class ClientPacketResender {
- private final List sentPackets;
- private final ClientPacketSender sender;
- private final PswgBasicThread resender;
- private final CongestionAvoidance congAvoidance;
- private final AtomicLong lastSent;
+ private final ResenderWrapper resender;
+ private final PswgBasicThread executor;
+ private final AtomicBoolean running;
public ClientPacketResender(ClientPacketSender sender) {
- this.sender = sender;
- this.sentPackets = new ArrayList<>(128);
- this.resender = new PswgBasicThread("packet-resender", () -> resendRunnable());
- this.congAvoidance = new CongestionAvoidance();
- this.lastSent = new AtomicLong(0);
+ this.resender = new ResenderWrapper(sender);
+ this.executor = new PswgBasicThread("packet-resender", this::resender);
+ this.running = new AtomicBoolean(false);
}
public void start(IntentManager intentManager) {
- resender.start();
intentManager.registerForIntent(ClientSonyPacketIntent.class, cspi -> handleClientPacket(cspi.getPacket()));
intentManager.registerForIntent(ClientConnectionChangedIntent.class, ccci -> handleClientStatusChanged(ccci.getStatus()));
+
+ running.set(true);
+ executor.start();
}
public void stop() {
- resender.stop(true);
- resender.awaitTermination(1000);
- synchronized (sentPackets) {
- sentPackets.clear();
- }
+ running.set(false);
+ executor.stop(true);
+ executor.awaitTermination(500);
+ resender.reset();
}
- public void restart() {
- synchronized (sentPackets) {
- sentPackets.clear();
- }
+ public void add(SequencedOutbound out) {
+ resender.add(out);
}
- public void add(short sequence, byte [] data) {
- SequencedOutbound out = new SequencedOutbound(sequence, data);
- synchronized (sentPackets) {
- sentPackets.add(out);
- sentPackets.notifyAll();
+ private void resender() {
+ while (running.get()) {
+ resender.resend();
}
}
private void handleClientPacket(Packet p) {
if (p instanceof Acknowledge)
- onAcknowledge(((Acknowledge) p).getSequence());
+ resender.onAcknowledge(((Acknowledge) p).getSequence());
else if (p instanceof OutOfOrder)
- onOutOfOrder(((OutOfOrder) p).getSequence());
+ resender.onOutOfOrder(((OutOfOrder) p).getSequence());
}
private void handleClientStatusChanged(ClientConnectionStatus status) {
- restart();
+ resender.reset();
}
- private void onOutOfOrder(short sequence) {
- Log.w("OOO %d", sequence);
- synchronized (sentPackets) {
- congAvoidance.onOutOfOrder();
- updateRtt();
+ private static class ResenderWrapper {
+
+ private final List sentPackets;
+ private final CongestionAvoidance congAvoidance;
+ private final Lock sentPacketsLock;
+ private final Condition sentPacketsCondition;
+ private final Resender resender;
+
+ public ResenderWrapper(ClientPacketSender sender) {
+ this.sentPackets = new LinkedList<>();
+ this.congAvoidance = new CongestionAvoidance();
+ this.sentPacketsLock = new ReentrantLock(false);
+ this.sentPacketsCondition = sentPacketsLock.newCondition();
+ this.resender = new Resender(congAvoidance, sender);
}
- }
-
- private void onAcknowledge(short sequence) {
- int seqInt = sequence & 0xFFFF;
- SequencedOutbound out;
- synchronized (sentPackets) {
- while (!sentPackets.isEmpty()) {
- out = sentPackets.get(0);
- if (out.getSequenceInt() <= seqInt || (seqInt < 100 && out.getSequenceInt() > Short.MAX_VALUE-100)) {
- sentPackets.remove(0);
- } else {
- break;
- }
+
+ public void add(SequencedOutbound seq) {
+ sentPacketsLock.lock();
+ try {
+ sentPackets.add(seq);
+ sentPacketsCondition.signal();
+ } finally {
+ sentPacketsLock.unlock();
}
- updateRtt();
- congAvoidance.onAcknowledgement();
}
- }
-
- private void resendRunnable() {
- while (resender.isRunning()) {
- synchronized (sentPackets) {
- congAvoidance.markBeginningOfWindow();
- if (congAvoidance.getWindow() != 50 && congAvoidance.getAverageRTT() != Double.MAX_VALUE) {
- Log.d("Congestion Window: %d Average RTT: %.3fms", congAvoidance.getWindow(), congAvoidance.getAverageRTT()/1E6);
+
+ public void reset() {
+ sentPacketsLock.lock();
+ try {
+ sentPackets.clear();
+ } finally {
+ sentPacketsLock.unlock();
+ }
+ }
+
+ public void onOutOfOrder(short sequence) {
+ Log.w("OOO %d", sequence);
+ sentPacketsLock.lock();
+ try {
+ congAvoidance.onOutOfOrder();
+ } finally {
+ sentPacketsLock.unlock();
+ }
+ }
+
+ public void onAcknowledge(short sequence) {
+ sentPacketsLock.lock();
+ try {
+ int seqInt = sequence & 0xFFFF;
+ SequencedOutbound out;
+ while (!sentPackets.isEmpty()) {
+ out = sentPackets.get(0);
+ if (out.getSequenceInt() <= seqInt || (seqInt < 100 && out.getSequenceInt() > Short.MAX_VALUE-100)) {
+ sentPackets.remove(0);
+ } else {
+ break;
+ }
}
- boolean lossEvent = !sentPackets.isEmpty() && (congAvoidance.isTimedOut() || congAvoidance.isTripleACK());
- if (lossEvent) {
- Log.w("Resender: Loss Event!");
- }
- sendAllInWindow();
- if (sentPackets.size() < 100) {
- casualWindowIteration(lossEvent);
- } else {
- intenseWindowIteration(lossEvent);
- }
- congAvoidance.markEndOfWindow();
- if (waitForPacket())
- continue;
+ congAvoidance.onAcknowledgement();
+ } finally {
+ sentPacketsLock.unlock();
+ }
+ }
+
+ public void resend() {
+ sentPacketsLock.lock();
+ try {
+ waitForPacket();
+ resender.handle(sentPackets);
+ } finally {
+ sentPacketsLock.unlock();
}
waitForTimeoutOrAck();
}
- }
-
- private void updateRtt() {
- long lastRtt = getTimeSinceSent();
- clearTimeSinceSent();
- if (lastRtt > 0)
- congAvoidance.updateRtt(lastRtt);
- }
-
- private void waitForTimeoutOrAck() {
- double avg = congAvoidance.getAverageRTT();
- if (avg == Double.MAX_VALUE)
- Delay.sleepMicro(5);
- else
- Delay.sleepNano((long) Math.min(1E9, Math.max(5E6, avg)));
- }
-
- private boolean waitForPacket() {
- if (!sentPackets.isEmpty())
- return false;
- try {
- while (sentPackets.isEmpty()) {
- sentPackets.wait();
+
+ private void waitForPacket() {
+ if (!sentPackets.isEmpty())
+ return;
+ try {
+ while (sentPackets.isEmpty()) {
+ sentPacketsCondition.await();
+ }
+ } catch (InterruptedException e) {
+
}
- } catch (InterruptedException e) {
+ congAvoidance.clearTimeSinceSent();
}
- clearTimeSinceSent();
- return true;
- }
-
- /**
- * This congestion avoidance algorithm focuses more on slow window
- * increases/decreases. This is ideal for casual gameplay where there
- * aren't many packets being sent at once.
- */
- private void casualWindowIteration(boolean lossEvent) {
- if (lossEvent) {
- congAvoidance.setWindow(Math.max(10, congAvoidance.getWindow() - 5));
- } else {
- congAvoidance.setWindow(Math.min(50, congAvoidance.getWindow() + 5));
+
+ private void waitForTimeoutOrAck() {
+ double avg = congAvoidance.getAverageRTT();
+ if (avg == Double.MAX_VALUE)
+ Delay.sleepMicro(5);
+ else
+ Delay.sleepNano((long) Math.min(1E9, Math.max(5E6, avg)));
}
+
}
- /**
- * This congestion avoidance algorithm focuses on fast window
- * increases/decreases. This is ideal for zone-in where as many packets as
- * possible need to be sent as fast as possible.
- */
- private void intenseWindowIteration(boolean lossEvent) {
- int window = congAvoidance.getWindow();
- if (window > sentPackets.size())
- return;
- if (lossEvent) {
- congAvoidance.setWindow(Math.max(50, window / 4));
- } else {
- congAvoidance.setWindow((int) (window * 1.5));
+ private static class Resender {
+
+ private final CongestionAvoidance congAvoidance;
+ private final ClientPacketSender sender;
+
+ public Resender(CongestionAvoidance congAvoidance, ClientPacketSender sender) {
+ this.congAvoidance = congAvoidance;
+ this.sender = sender;
}
- }
-
- private void sendAllInWindow() {
- int max = congAvoidance.getWindow();
- for (SequencedOutbound out : sentPackets) {
- if (--max < 0)
- break;
- sender.sendRaw(out.getData());
- congAvoidance.onSentPacket();
+
+ public void handle(List sentPackets) {
+ congAvoidance.markBeginningOfWindow();
+ int sentPacketCount = sentPackets.size();
+ boolean lossEvent = sentPacketCount > 0 && (congAvoidance.isTimedOut() || congAvoidance.isTripleACK());
+
+ printStatus(lossEvent);
+ sendAllInWindow(sentPackets);
+ if (sentPacketCount < 100) {
+ casualWindowIteration(lossEvent);
+ } else {
+ intenseWindowIteration(lossEvent, sentPacketCount);
+ }
+ congAvoidance.markEndOfWindow();
}
- updateTimeSinceSent();
- }
-
- private void updateTimeSinceSent() {
- lastSent.compareAndSet(0, System.nanoTime());
- }
-
- private long getTimeSinceSent() {
- long sent = lastSent.get();
- if (sent == 0)
- return -1;
- return System.nanoTime() - sent;
- }
-
- private void clearTimeSinceSent() {
- lastSent.set(0);
+
+ private void printStatus(boolean lossEvent) {
+ if (congAvoidance.getWindow() != 50 && congAvoidance.getAverageRTT() != Double.MAX_VALUE)
+ Log.d("Resender: Congestion Window: %d Average RTT: %.3fms", congAvoidance.getWindow(), congAvoidance.getAverageRTT()/1E6);
+
+ if (lossEvent)
+ Log.w("Resender: Loss Event!");
+ }
+
+ /**
+ * This congestion avoidance algorithm focuses more on slow window
+ * increases/decreases. This is ideal for casual gameplay where there
+ * aren't many packets being sent at once.
+ */
+ private void casualWindowIteration(boolean lossEvent) {
+ if (lossEvent) {
+ congAvoidance.setWindow(Math.max(10, congAvoidance.getWindow() - 5));
+ } else {
+ congAvoidance.setWindow(Math.min(50, congAvoidance.getWindow() + 5));
+ }
+ }
+
+ /**
+ * This congestion avoidance algorithm focuses on fast window
+ * increases/decreases. This is ideal for zone-in where as many packets as
+ * possible need to be sent as fast as possible.
+ */
+ private void intenseWindowIteration(boolean lossEvent, int sentPackets) {
+ int window = congAvoidance.getWindow();
+ if (window > sentPackets)
+ return;
+ if (lossEvent) {
+ congAvoidance.setWindow(Math.max(50, window / 4));
+ } else {
+ congAvoidance.setWindow((int) (window * 1.5));
+ }
+ }
+
+ private void sendAllInWindow(List sentPackets) {
+ int max = congAvoidance.getWindow();
+ for (SequencedOutbound out : sentPackets) {
+ if (--max < 0)
+ break;
+ sender.sendRaw(out.getData());
+ congAvoidance.onSentPacket();
+ }
+ congAvoidance.updateTimeSinceSent();
+ }
+
}
private static class CongestionAvoidance {
// Higher-level properties
+ private long lastSent;
private double averageRtt;
private int congestionWindow;
@@ -226,25 +262,22 @@ public class ClientPacketResender {
}
public void reset() {
+ this.lastSent = 0;
+ this.congestionWindow = 1;
+
this.outOfOrders = 0;
this.acknowledgements = 0;
this.sentPackets = 0;
this.missedWindows = 0;
- this.congestionWindow = 1;
}
public void onOutOfOrder() {
+ updateRtt();
this.outOfOrders++;
}
- public void updateRtt(long lastRtt) {
- if (this.averageRtt == Double.MAX_VALUE)
- this.averageRtt = lastRtt;
- else
- this.averageRtt = averageRtt * 0.875 + lastRtt * 0.125;
- }
-
public void onAcknowledgement() {
+ updateRtt();
this.outOfOrders = 0;
this.acknowledgements++;
}
@@ -285,43 +318,27 @@ public class ClientPacketResender {
return missedWindows >= 2 && averageRtt != Double.MAX_VALUE;
}
- }
-
- private static class SequencedOutbound implements SequencedPacket {
-
- private int sequence;
- private byte [] data;
-
- public SequencedOutbound(short sequence, byte [] data) {
- this.sequence = sequence & 0xFFFF;
- this.data = data;
+ public void updateTimeSinceSent() {
+ if (lastSent == 0)
+ lastSent = System.nanoTime();
}
- @Override
- public short getSequence() { return (short) sequence; }
- public int getSequenceInt() { return sequence; }
- public byte [] getData() { return data; }
-
- @Override
- public int compareTo(SequencedPacket p) {
- if (getSequence() < p.getSequence())
- return -1;
- if (getSequence() == p.getSequence())
- return 0;
- return 1;
+ private void updateRtt() {
+ long lastRtt = lastSent;
+ lastSent = 0;
+ if (lastRtt <= 0)
+ return;
+ lastRtt = System.nanoTime() - lastRtt;
+
+ if (this.averageRtt == Double.MAX_VALUE)
+ this.averageRtt = lastRtt;
+ else
+ this.averageRtt = averageRtt * 0.875 + lastRtt * 0.125;
}
- @Override
- public boolean equals(Object o) {
- if (!(o instanceof SequencedOutbound))
- return super.equals(o);
- return ((SequencedOutbound) o).getSequence() == sequence;
+ public void clearTimeSinceSent() {
+ lastSent = 0;
}
- @Override
- public int hashCode() {
- return sequence;
- }
- }
-
+ }
}
diff --git a/src/com/projectswg/networking/client/sender/SequencedOutbound.java b/src/com/projectswg/networking/client/sender/SequencedOutbound.java
new file mode 100644
index 0000000..0f35cca
--- /dev/null
+++ b/src/com/projectswg/networking/client/sender/SequencedOutbound.java
@@ -0,0 +1,40 @@
+package com.projectswg.networking.client.sender;
+
+import com.projectswg.networking.soe.SequencedPacket;
+
+public class SequencedOutbound implements SequencedPacket {
+
+ private final int sequence;
+ private final byte [] data;
+
+ public SequencedOutbound(short sequence, byte [] data) {
+ this.sequence = sequence & 0xFFFF;
+ this.data = data;
+ }
+
+ @Override
+ public short getSequence() { return (short) sequence; }
+ public int getSequenceInt() { return sequence; }
+ public byte [] getData() { return data; }
+
+ @Override
+ public int compareTo(SequencedPacket p) {
+ if (getSequence() < p.getSequence())
+ return -1;
+ if (getSequence() == p.getSequence())
+ return 0;
+ return 1;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof SequencedOutbound))
+ return super.equals(o);
+ return ((SequencedOutbound) o).getSequence() == sequence;
+ }
+
+ @Override
+ public int hashCode() {
+ return sequence;
+ }
+}
diff --git a/src/com/projectswg/networking/encryption/CRC.java b/src/com/projectswg/networking/encryption/CRC.java
deleted file mode 100644
index 5b3354e..0000000
--- a/src/com/projectswg/networking/encryption/CRC.java
+++ /dev/null
@@ -1,181 +0,0 @@
-/***********************************************************************************
-* Copyright (c) 2015 /// Project SWG /// www.projectswg.com *
-* *
-* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
-* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
-* Our goal is to create an emulator which will provide a server for players to *
-* continue playing a game similar to the one they used to play. We are basing *
-* it on the final publish of the game prior to end-game events. *
-* *
-* This file is part of Holocore. *
-* *
-* -------------------------------------------------------------------------------- *
-* *
-* Holocore is free software: you can redistribute it and/or modify *
-* it under the terms of the GNU Affero General Public License as *
-* published by the Free Software Foundation, either version 3 of the *
-* License, or (at your option) any later version. *
-* *
-* Holocore 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 Affero General Public License for more details. *
-* *
-* You should have received a copy of the GNU Affero General Public License *
-* along with Holocore. If not, see . *
-* *
-***********************************************************************************/
-package com.projectswg.networking.encryption;
-
-import java.nio.charset.StandardCharsets;
-
-public class CRC {
-
- private static final int CRC_TABLE[] = {
- 0x0000000,
- 0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B,
- 0x1A864DB2, 0x1E475005, 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6,
- 0x2B4BCB61, 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD,
- 0x4C11DB70, 0x48D0C6C7, 0x4593E01E, 0x4152FDA9, 0x5F15ADAC,
- 0x5BD4B01B, 0x569796C2, 0x52568B75, 0x6A1936C8, 0x6ED82B7F,
- 0x639B0DA6, 0x675A1011, 0x791D4014, 0x7DDC5DA3, 0x709F7B7A,
- 0x745E66CD, 0x9823B6E0, 0x9CE2AB57, 0x91A18D8E, 0x95609039,
- 0x8B27C03C, 0x8FE6DD8B, 0x82A5FB52, 0x8664E6E5, 0xBE2B5B58,
- 0xBAEA46EF, 0xB7A96036, 0xB3687D81, 0xAD2F2D84, 0xA9EE3033,
- 0xA4AD16EA, 0xA06C0B5D, 0xD4326D90, 0xD0F37027, 0xDDB056FE,
- 0xD9714B49, 0xC7361B4C, 0xC3F706FB, 0xCEB42022, 0xCA753D95,
- 0xF23A8028, 0xF6FB9D9F, 0xFBB8BB46, 0xFF79A6F1, 0xE13EF6F4,
- 0xE5FFEB43, 0xE8BCCD9A, 0xEC7DD02D, 0x34867077, 0x30476DC0,
- 0x3D044B19, 0x39C556AE, 0x278206AB, 0x23431B1C, 0x2E003DC5,
- 0x2AC12072, 0x128E9DCF, 0x164F8078, 0x1B0CA6A1, 0x1FCDBB16,
- 0x018AEB13, 0x054BF6A4, 0x0808D07D, 0x0CC9CDCA, 0x7897AB07,
- 0x7C56B6B0, 0x71159069, 0x75D48DDE, 0x6B93DDDB, 0x6F52C06C,
- 0x6211E6B5, 0x66D0FB02, 0x5E9F46BF, 0x5A5E5B08, 0x571D7DD1,
- 0x53DC6066, 0x4D9B3063, 0x495A2DD4, 0x44190B0D, 0x40D816BA,
- 0xACA5C697, 0xA864DB20, 0xA527FDF9, 0xA1E6E04E, 0xBFA1B04B,
- 0xBB60ADFC, 0xB6238B25, 0xB2E29692, 0x8AAD2B2F, 0x8E6C3698,
- 0x832F1041, 0x87EE0DF6, 0x99A95DF3, 0x9D684044, 0x902B669D,
- 0x94EA7B2A, 0xE0B41DE7, 0xE4750050, 0xE9362689, 0xEDF73B3E,
- 0xF3B06B3B, 0xF771768C, 0xFA325055, 0xFEF34DE2, 0xC6BCF05F,
- 0xC27DEDE8, 0xCF3ECB31, 0xCBFFD686, 0xD5B88683, 0xD1799B34,
- 0xDC3ABDED, 0xD8FBA05A, 0x690CE0EE, 0x6DCDFD59, 0x608EDB80,
- 0x644FC637, 0x7A089632, 0x7EC98B85, 0x738AAD5C, 0x774BB0EB,
- 0x4F040D56, 0x4BC510E1, 0x46863638, 0x42472B8F, 0x5C007B8A,
- 0x58C1663D, 0x558240E4, 0x51435D53, 0x251D3B9E, 0x21DC2629,
- 0x2C9F00F0, 0x285E1D47, 0x36194D42, 0x32D850F5, 0x3F9B762C,
- 0x3B5A6B9B, 0x0315D626, 0x07D4CB91, 0x0A97ED48, 0x0E56F0FF,
- 0x1011A0FA, 0x14D0BD4D, 0x19939B94, 0x1D528623, 0xF12F560E,
- 0xF5EE4BB9, 0xF8AD6D60, 0xFC6C70D7, 0xE22B20D2, 0xE6EA3D65,
- 0xEBA91BBC, 0xEF68060B, 0xD727BBB6, 0xD3E6A601, 0xDEA580D8,
- 0xDA649D6F, 0xC423CD6A, 0xC0E2D0DD, 0xCDA1F604, 0xC960EBB3,
- 0xBD3E8D7E, 0xB9FF90C9, 0xB4BCB610, 0xB07DABA7, 0xAE3AFBA2,
- 0xAAFBE615, 0xA7B8C0CC, 0xA379DD7B, 0x9B3660C6, 0x9FF77D71,
- 0x92B45BA8, 0x9675461F, 0x8832161A, 0x8CF30BAD, 0x81B02D74,
- 0x857130C3, 0x5D8A9099, 0x594B8D2E, 0x5408ABF7, 0x50C9B640,
- 0x4E8EE645, 0x4A4FFBF2, 0x470CDD2B, 0x43CDC09C, 0x7B827D21,
- 0x7F436096, 0x7200464F, 0x76C15BF8, 0x68860BFD, 0x6C47164A,
- 0x61043093, 0x65C52D24, 0x119B4BE9, 0x155A565E, 0x18197087,
- 0x1CD86D30, 0x029F3D35, 0x065E2082, 0x0B1D065B, 0x0FDC1BEC,
- 0x3793A651, 0x3352BBE6, 0x3E119D3F, 0x3AD08088, 0x2497D08D,
- 0x2056CD3A, 0x2D15EBE3, 0x29D4F654, 0xC5A92679, 0xC1683BCE,
- 0xCC2B1D17, 0xC8EA00A0, 0xD6AD50A5, 0xD26C4D12, 0xDF2F6BCB,
- 0xDBEE767C, 0xE3A1CBC1, 0xE760D676, 0xEA23F0AF, 0xEEE2ED18,
- 0xF0A5BD1D, 0xF464A0AA, 0xF9278673, 0xFDE69BC4, 0x89B8FD09,
- 0x8D79E0BE, 0x803AC667, 0x84FBDBD0, 0x9ABC8BD5, 0x9E7D9662,
- 0x933EB0BB, 0x97FFAD0C, 0xAFB010B1, 0xAB710D06, 0xA6322BDF,
- 0xA2F33668, 0xBCB4666D, 0xB8757BDA, 0xB5365D03, 0xB1F740B4,
- };
-
- private static final int[] CRC_ZIP_TABLE = {
- 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
- 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
- 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
- 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
- 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
- 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
- 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
- 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
- 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
- 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
- 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
- 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
- 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
- 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
- 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
- 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
- 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
- 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
- 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
- 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
- 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
- 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
- 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
- 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
- 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
- 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
- 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
- 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
- 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
- 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
- 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
- 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
- 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
- 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
- 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
- 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
- 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
- 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
- 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
- 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
- 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
- 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
- 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
- };
-
- public static int getCrc(String input) {
- byte [] bytes = input.getBytes(StandardCharsets.UTF_8);
- int crc = 0xffffffff;
-
- for (int i = 0; i < bytes.length; ++i) {
- crc = CRC_TABLE[(int) (bytes[i] ^ (crc >> 24)) & 0x000000FF] ^ (crc << 8);
- }
- return (int) ~crc;
- }
-
- public static int memcrc(String input) {
- byte [] bytes = input.getBytes(StandardCharsets.UTF_8);
-
- int crc = 0xffffffff;
- for (int i = 0; i < bytes.length; ++i) {
- crc = CRC_TABLE[(int) (bytes[i] ^ (crc >> 24)) & 0x000000FF] ^ (crc << 8);
- }
-
- return (int) ~crc;
- }
-
- public static int memcrc(byte [] src_buffer, int offset, int length, int seed) {
- int index;
- int newCRC = 0;
-
- newCRC = CRC_ZIP_TABLE[(~seed) & 0xFF];
- newCRC ^= 0x00FFFFFF;
- index = (seed >> 8) ^ newCRC;
- newCRC = (newCRC >> 8) & 0x00FFFFFF;
- newCRC ^= CRC_ZIP_TABLE[index & 0xFF];
- index = (seed >> 16) ^ newCRC;
- newCRC = (newCRC >> 8) & 0x00FFFFFF;
- newCRC ^= CRC_ZIP_TABLE[index & 0xFF];
- index = (seed >> 24) ^ newCRC;
- newCRC = (newCRC >> 8) & 0x00FFFFFF;
- newCRC ^= CRC_ZIP_TABLE[index & 0xFF];
-
- for (int i = offset; i < length; i++) {
- index = (src_buffer[i]) ^ newCRC;
- newCRC = (newCRC >> 8) & 0x00FFFFFF;
- newCRC ^= CRC_ZIP_TABLE[index & 0xFF];
- }
-
- return ~newCRC;
- }
-
-}
diff --git a/src/com/projectswg/networking/resources/Galaxy.java b/src/com/projectswg/networking/resources/Galaxy.java
deleted file mode 100644
index 8491824..0000000
--- a/src/com/projectswg/networking/resources/Galaxy.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/***********************************************************************************
-* Copyright (c) 2015 /// Project SWG /// www.projectswg.com *
-* *
-* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
-* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
-* Our goal is to create an emulator which will provide a server for players to *
-* continue playing a game similar to the one they used to play. We are basing *
-* it on the final publish of the game prior to end-game events. *
-* *
-* This file is part of Holocore. *
-* *
-* -------------------------------------------------------------------------------- *
-* *
-* Holocore is free software: you can redistribute it and/or modify *
-* it under the terms of the GNU Affero General Public License as *
-* published by the Free Software Foundation, either version 3 of the *
-* License, or (at your option) any later version. *
-* *
-* Holocore 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 Affero General Public License for more details. *
-* *
-* You should have received a copy of the GNU Affero General Public License *
-* along with Holocore. If not, see . *
-* *
-***********************************************************************************/
-package com.projectswg.networking.resources;
-
-
-public class Galaxy {
-
- private int id = 0;
- private String name = "";
- private String address = "";
- private short zonePort = (short) 44463;
- private short pingPort = (short) 44462;
- private int population = 0;
- private int popStatus = 0;
- private GalaxyStatus status = GalaxyStatus.DOWN;
- private int timeZone = 0;
- private int maxCharacters = 0;
- private int onlinePlayerLimit = 0;
- private int onlineFreeTrialLimit = 0;
- private boolean recommended = true;
-
- public Galaxy() {
-
- }
-
- public int getId() { return id; }
- public String getName() { return name; }
- public String getAddress() { return address; }
- public short getZonePort() { return zonePort; }
- public short getPingPort() { return pingPort; }
- public int getPopulation() { return population; }
- public int getPopulationStatus() { return popStatus; }
- public GalaxyStatus getStatus() { return status; }
- public int getTimeZone() { return timeZone; }
- public int getMaxCharacters() { return maxCharacters; }
- public int getOnlinePlayerLimit() { return onlinePlayerLimit; }
- public int getOnlineFreeTrialLimit() { return onlineFreeTrialLimit; }
- public boolean isRecommended() { return recommended; }
-
- public void setId(int id) { this.id = id; }
- public void setName(String name) { this.name = name; }
- public void setAddress(String addr) { this.address = addr; }
- public void setZonePort(short port) { this.zonePort = port; }
- public void setPingPort(short port) { this.pingPort = port; }
- public void setPopulation(int population) { this.population = population; }
- public void setPopulationStatus(int status) { this.popStatus = status; }
- public void setStatus(GalaxyStatus status) { this.status = status; }
- public void setTimeZone(int timeZone) { this.timeZone = timeZone; }
- public void setMaxCharacters(int max) { this.maxCharacters = max; }
- public void setOnlinePlayerLimit(int max) { this.onlinePlayerLimit = max; }
- public void setOnlineFreeTrialLimit(int max) { this.onlineFreeTrialLimit = max; }
- public void setRecommended(boolean r) { this.recommended = r; }
-
- public String toString() {
- return String.format("Galaxy[ID=%d Name=%s Address=%s Zone=%d Ping=%d Pop=%d PopStat=%d Status=%s Time=%d Max=%d Rec=%b]",
- id, name, address, zonePort, pingPort, population, popStatus, status, timeZone, maxCharacters, recommended);
- }
-
- public void setStatus(int status) {
- for (GalaxyStatus gs : GalaxyStatus.values()) {
- if (gs.getStatus() == status) {
- setStatus(gs);
- return;
- }
- }
- }
-
- public enum GalaxyStatus {
- DOWN (0x00),
- LOADING (0x01),
- UP (0x02),
- LOCKED (0x03),
- RESTRICTED (0x04),
- FULL (0x05);
-
- private byte status;
-
- GalaxyStatus(int status) {
- this.status = (byte) status;
- }
-
- public byte getStatus() {
- return status;
- }
- }
-
-}
diff --git a/src/com/projectswg/networking/server/ServerConnectionService.java b/src/com/projectswg/networking/server/ServerConnectionService.java
index 2b02da7..1b8c35f 100644
--- a/src/com/projectswg/networking/server/ServerConnectionService.java
+++ b/src/com/projectswg/networking/server/ServerConnectionService.java
@@ -15,6 +15,7 @@ import com.projectswg.common.control.IntentManager;
import com.projectswg.common.control.Service;
import com.projectswg.common.debug.Assert;
import com.projectswg.common.debug.Log;
+import com.projectswg.common.network.packets.swg.zone.HeartBeat;
import com.projectswg.connection.HolocoreSocket;
import com.projectswg.connection.ServerConnectionChangedReason;
import com.projectswg.connection.packets.RawPacket;
@@ -23,8 +24,6 @@ import com.projectswg.intents.ClientToServerPacketIntent;
import com.projectswg.intents.ServerConnectionChangedIntent;
import com.projectswg.intents.ServerToClientPacketIntent;
-import com.projectswg.common.network.packets.swg.zone.HeartBeat;
-
public class ServerConnectionService extends Service {
private static final long HOLOCORE_TIMEOUT = TimeUnit.SECONDS.toNanos(21);