Added wait for client to acknowledge, for sending final packets

This commit is contained in:
Josh Larson
2017-01-09 02:09:50 -06:00
parent a712a8222d
commit dcfda1eb28
8 changed files with 141 additions and 6 deletions

View File

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

View File

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

View File

@@ -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) {

View File

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

View File

@@ -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 <http://www.gnu.org/licenses/>. *
* *
***********************************************************************************/
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
}
}

View File

@@ -52,7 +52,6 @@ public class IntentManager {
public IntentManager() {
intentRegistrations = new HashMap<String, Set<IntentReceiver>>();
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);
}

View File

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

View File

@@ -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);
}