diff --git a/src/com/projectswg/ClientConnection.java b/src/com/projectswg/ClientConnection.java
index afc81cf..dfedfef 100644
--- a/src/com/projectswg/ClientConnection.java
+++ b/src/com/projectswg/ClientConnection.java
@@ -6,6 +6,8 @@ import com.projectswg.control.Manager;
import com.projectswg.networking.NetInterceptor;
import com.projectswg.networking.Packet;
import com.projectswg.networking.NetInterceptor.InterceptorProperties;
+import com.projectswg.networking.soe.Disconnect;
+import com.projectswg.networking.soe.Disconnect.DisconnectReason;
public class ClientConnection extends Manager {
@@ -36,6 +38,16 @@ public class ClientConnection extends Manager {
return true;
}
+ public void disconnect(DisconnectReason reason) {
+ sender.send(new Disconnect(sender.getConnectionId(), reason));
+ }
+
+ public void waitForClientAcknowledge() throws InterruptedException {
+ while (sender.getTransmittedSequence()-1 > receiver.getAckSequence()) {
+ Thread.sleep(1);
+ }
+ }
+
public void hardReset() {
sender.hardReset();
receiver.hardReset();
diff --git a/src/com/projectswg/ClientReceiver.java b/src/com/projectswg/ClientReceiver.java
index a87b06d..436b742 100644
--- a/src/com/projectswg/ClientReceiver.java
+++ b/src/com/projectswg/ClientReceiver.java
@@ -55,6 +55,7 @@ public class ClientReceiver extends Service {
private ClientSender sender;
private ClientConnectionStatus status;
private short rxSequence;
+ private short ackSequence;
private int port;
private boolean zone;
@@ -66,6 +67,8 @@ public class ClientReceiver extends Service {
this.stateIntentChain = new IntentChain();
this.timeout = timeout;
this.status = ClientConnectionStatus.DISCONNECTED;
+ this.rxSequence = -1;
+ this.ackSequence = -1;
}
@Override
@@ -120,6 +123,8 @@ public class ClientReceiver extends Service {
onDataChannel((DataChannelA) p);
else if (p instanceof Fragmented)
onFragmented((Fragmented) p);
+ else if (p instanceof Acknowledge)
+ onAcknowledge((Acknowledge) p);
}
}
@@ -127,6 +132,10 @@ public class ClientReceiver extends Service {
this.sender = sender;
}
+ public short getAckSequence() {
+ return ackSequence;
+ }
+
public void reset() {
rxSequence = -1;
}
@@ -301,6 +310,10 @@ public class ClientReceiver extends Service {
process(combined);
}
+ private void onAcknowledge(Acknowledge ack) {
+ this.ackSequence = ack.getSequence();
+ }
+
private void onSWGPacket(byte [] data) {
data = interceptor.interceptClient(data);
recvIntentChain.broadcastAfter(new ClientToServerPacketIntent(data), getIntentManager());
diff --git a/src/com/projectswg/ClientSender.java b/src/com/projectswg/ClientSender.java
index f953d17..9d82201 100644
--- a/src/com/projectswg/ClientSender.java
+++ b/src/com/projectswg/ClientSender.java
@@ -102,6 +102,10 @@ public class ClientSender extends Service {
return super.stop();
}
+ public short getTransmittedSequence() {
+ return packager.getSequence();
+ }
+
@Override
public void onIntentReceived(Intent i) {
if (i instanceof ServerToClientPacketIntent) {
diff --git a/src/com/projectswg/Connections.java b/src/com/projectswg/Connections.java
index f64ebe1..729f4d5 100644
--- a/src/com/projectswg/Connections.java
+++ b/src/com/projectswg/Connections.java
@@ -13,6 +13,7 @@ import com.projectswg.intents.ClientToServerPacketIntent;
import com.projectswg.intents.ServerConnectionChangedIntent;
import com.projectswg.intents.ServerToClientPacketIntent;
import com.projectswg.networking.NetInterceptor.InterceptorProperties;
+import com.projectswg.networking.soe.Disconnect.DisconnectReason;
import com.projectswg.resources.ClientConnectionStatus;
import com.projectswg.resources.ServerConnectionStatus;
import com.projectswg.services.PacketRecordingService;
@@ -140,6 +141,12 @@ public class Connections extends Manager {
error += "\nInstalled Version: " + VERSION;
client.send(new ErrorMessage("Network", error, false));
}
+ try {
+ client.waitForClientAcknowledge();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ client.disconnect(DisconnectReason.OTHER_SIDE_TERMINATED);
client.hardReset();
}
}
diff --git a/src/com/projectswg/control/Assert.java b/src/com/projectswg/control/Assert.java
new file mode 100644
index 0000000..6a48039
--- /dev/null
+++ b/src/com/projectswg/control/Assert.java
@@ -0,0 +1,101 @@
+/***********************************************************************************
+* 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.control;
+
+import resources.server_info.Log;
+
+public class Assert {
+
+ private static volatile AssertLevel level = AssertLevel.ASSERT;
+
+ public static void setLevel(AssertLevel level) {
+ Assert.level = level;
+ }
+
+ public static boolean debug() {
+ return level != AssertLevel.IGNORE;
+ }
+
+ public static void notNull(Object o) {
+ if (debug() && o == null)
+ handle(new NullPointerException());
+ }
+
+ public static void isNull(Object o) {
+ if (debug() && o != null)
+ handle(new AssertionException());
+ }
+
+ public static void test(boolean expr) {
+ if (debug() && !expr)
+ handle(new AssertionException());
+ }
+
+ public static void fail() {
+ if (debug())
+ handle(new AssertionException());
+ }
+
+ private static void handle(RuntimeException e) {
+ AssertLevel level = Assert.level;
+ switch (level) {
+ case WARN:
+ warn(e);
+ break;
+ case ASSERT:
+ throw e;
+ default:
+ break;
+ }
+ }
+
+ private static void warn(Exception e) {
+ StackTraceElement [] elements = e.getStackTrace();
+ if (elements.length <= 1)
+ Log.e("Assert", e);
+ else
+ Log.e(elements[elements.length-2].getClassName(), e);
+ }
+
+ private static class AssertionException extends RuntimeException {
+
+ private static final long serialVersionUID = 1L;
+
+ public AssertionException() {
+ super("");
+ }
+
+ }
+
+ public enum AssertLevel {
+ IGNORE,
+ WARN,
+ ASSERT
+ }
+
+}
diff --git a/src/com/projectswg/control/IntentManager.java b/src/com/projectswg/control/IntentManager.java
index 50fa969..9259d73 100644
--- a/src/com/projectswg/control/IntentManager.java
+++ b/src/com/projectswg/control/IntentManager.java
@@ -52,7 +52,6 @@ public class IntentManager {
public IntentManager() {
intentRegistrations = new HashMap>();
intentQueue = new IntentQueue();
- initialize();
broadcastRunnable = () -> {
Intent i;
synchronized (intentQueue) {
@@ -82,8 +81,7 @@ public class IntentManager {
protected void broadcastIntent(Intent i) {
if (i == null)
throw new NullPointerException("Intent cannot be null!");
- if (!initialized)
- return;
+ Assert.test(initialized);
synchronized (intentQueue) {
intentQueue.add(i);
}
diff --git a/src/com/projectswg/networking/NetInterceptor.java b/src/com/projectswg/networking/NetInterceptor.java
index cf77a4a..69df27b 100644
--- a/src/com/projectswg/networking/NetInterceptor.java
+++ b/src/com/projectswg/networking/NetInterceptor.java
@@ -67,7 +67,6 @@ public class NetInterceptor {
g.setAddress("127.0.0.1");
g.setZonePort((short) properties.getPort());
g.setPingPort((short) properties.getPort());
- g.setPopulation(-1);
}
return cluster.encode().array();
}
diff --git a/src/com/projectswg/networking/soe/Acknowledge.java b/src/com/projectswg/networking/soe/Acknowledge.java
index a9d1dad..7de1659 100644
--- a/src/com/projectswg/networking/soe/Acknowledge.java
+++ b/src/com/projectswg/networking/soe/Acknowledge.java
@@ -29,6 +29,8 @@ package com.projectswg.networking.soe;
import java.nio.ByteBuffer;
+import resources.control.Assert;
+
import com.projectswg.networking.Packet;
public class Acknowledge extends Packet {
@@ -48,8 +50,7 @@ public class Acknowledge extends Packet {
}
public void decode(ByteBuffer data) {
- if (data.array().length < 4)
- return;
+ Assert.test(data.array().length == 4);
data.position(2);
sequence = getNetShort(data);
}