Fixed character creation screen loading and the "double enter" bug

This commit is contained in:
Josh Larson
2018-06-11 21:46:08 -05:00
parent 389d2323e4
commit 38c3e189ee
14 changed files with 167 additions and 43 deletions

View File

@@ -4,6 +4,7 @@ import com.projectswg.forwarder.resources.networking.ClientServer;
import com.projectswg.forwarder.resources.networking.packets.Fragmented;
import com.projectswg.forwarder.resources.networking.packets.Packet;
import com.projectswg.forwarder.resources.networking.packets.SequencedPacket;
import me.joshlarson.jlcommon.log.Log;
import org.jetbrains.annotations.NotNull;
import java.net.InetSocketAddress;
@@ -46,6 +47,7 @@ public class ProtocolStack {
}
public void send(Packet packet) {
Log.t("Sending %s", packet);
send(packet.encode().array());
}
@@ -166,4 +168,9 @@ public class ProtocolStack {
return Collections.unmodifiableCollection(outboundPackaged);
}
@Override
public String toString() {
return String.format("ProtocolStack[server=%s, source=%s, connectionId=%d]", server, source, connectionId);
}
}

View File

@@ -62,4 +62,9 @@ public class Acknowledge extends Packet {
public short getSequence() { return sequence; }
@Override
public String toString() {
return String.format("Acknowledge[%d]", sequence);
}
}

View File

@@ -102,4 +102,10 @@ public class ClientNetworkStatusUpdate extends Packet {
public void setLastServerUpdate(int last) { this.lastServerUpdate = last; }
public void setPacketsSent(long sent) { this.packetSent = sent; }
public void setPacketsRecv(long recv) { this.packetRecv = recv; }
@Override
public String toString() {
return String.format("ClientNetworkStatusUpdate[tick=%d, lastUpdate=%d, avgUpdate=%d, shortestUpdate=%d, longestUpdate=%d, lastServerUpdate=%d, sent=%d, recv=%d]", clientTickCount, lastUpdate, avgUpdate, shortUpdate, longUpdate, lastServerUpdate, packetSent, packetRecv);
}
}

View File

@@ -213,4 +213,9 @@ public class DataChannel extends Packet implements SequencedPacket {
}
}
@Override
public String toString() {
return String.format("DataChannel[seq=%d, packets=%d]", sequence, content.size());
}
}

View File

@@ -99,4 +99,10 @@ public class Disconnect extends Packet {
return reason;
}
}
@Override
public String toString() {
return String.format("Disconnect[id=%d, reason=%s]", connectionId, reason);
}
}

View File

@@ -133,4 +133,9 @@ public class Fragmented extends Packet implements SequencedPacket {
return f;
}
@Override
public String toString() {
return String.format("Fragmented[seq=%d, len=%d]", sequence, length);
}
}

View File

@@ -22,4 +22,9 @@ public class KeepAlive extends Packet {
return data;
}
@Override
public String toString() {
return String.format("KeepAlive[]");
}
}

View File

@@ -112,4 +112,9 @@ public class MultiPacket extends Packet {
return length;
}
@Override
public String toString() {
return String.format("MultiPacket[packets=%d]", content.size());
}
}

View File

@@ -58,4 +58,10 @@ public class OutOfOrder extends Packet {
}
public short getSequence() { return sequence; }
@Override
public String toString() {
return String.format("OutOfOrder[%d]", sequence);
}
}

View File

@@ -91,4 +91,10 @@ public class ServerNetworkStatusUpdate extends Packet {
public void setClientPacketsRecv(long recv) { this.clientPacketsRecv = recv; }
public void setServerPacketsSent(long sent) { this.serverPacketsSent = sent; }
public void setServerPacketsRecv(long recv) { this.serverPacketsRecv = recv; }
@Override
public String toString() {
return String.format("ServerNetworkStatusUpdate[ticks=%d, syncStamp=%d, clientSent=%d, clientRecv=%d, serverSent=%d, serverRecv=%d]", clientTickCount, serverSyncStampLong, clientPacketsSent, clientPacketsRecv, serverPacketsSent, serverPacketsRecv);
}
}

View File

@@ -71,4 +71,10 @@ public class SessionRequest extends Packet {
public int getCrcLength() { return crcLength; }
public int getConnectionId() { return connectionId; }
public int getUdpSize() { return udpSize; }
@Override
public String toString() {
return String.format("SessionRequest[connectionId=%d, crcLength=%d, udpSize=%d]", connectionId, crcLength, udpSize);
}
}

View File

@@ -92,4 +92,10 @@ public class SessionResponse extends Packet {
public void setEncryptionFlag(short flag) { this.encryptionFlag = (byte) flag; }
public void setXorLength(byte xorLength) { this.xorLength = xorLength; }
public void setUdpSize(int size) { this.udpSize = size; }
@Override
public String toString() {
return String.format("SessionResponse[connectionId=%d, crcSeed=%d, crcLength=%d, encryptionFlag=%d, xorLength=%d, udpSize=%d]", connectionId, crcSeed, crcLength, encryptionFlag, xorLength, udpSize);
}
}

View File

@@ -140,6 +140,8 @@ public class ClientServerService extends Service {
private void broadcast(InetSocketAddress source, ClientServer server, Packet parsed) {
ProtocolStack stack = this.stack.get();
if (parsed instanceof SessionRequest) {
if (stack != null && stack.getServer() == ClientServer.ZONE)
return;
stack = new ProtocolStack(source, server, (remote, data) -> send(remote, server, data));
stack.setConnectionId(((SessionRequest) parsed).getConnectionId());
setStack(stack);
@@ -154,20 +156,18 @@ public class ClientServerService extends Service {
Log.t("[%s]@%s sent: %s", source, server, parsed);
intentChain.broadcastAfter(getIntentManager(), new SonyPacketInboundIntent(parsed));
if (parsed instanceof Disconnect) {
Log.d("Received client disconnect with id %d and reason %s", ((Disconnect) parsed).getConnectionId(), ((Disconnect) parsed).getReason());
setStack(null);
}
}
private void setStack(ProtocolStack stack) {
Log.d("Updating stack: %s", stack);
ProtocolStack oldStack = this.stack.getAndSet(stack);
if (oldStack != null) {
oldStack.send(new Disconnect(oldStack.getConnectionId(), DisconnectReason.MANAGER_DELETED));
if (stack == null)
intentChain.broadcastAfter(getIntentManager(), new ClientDisconnectedIntent());
}
if (stack != null && stack.getServer() == ClientServer.LOGIN) {
if (oldStack != null && stack == null)
intentChain.broadcastAfter(getIntentManager(), new ClientDisconnectedIntent());
if (stack != null && stack.getServer() == ClientServer.LOGIN)
intentChain.broadcastAfter(getIntentManager(), new ClientConnectedIntent());
}
intentChain.broadcastAfter(getIntentManager(), new UpdateStackIntent(stack));
}

View File

@@ -1,8 +1,10 @@
package com.projectswg.forwarder.services.server;
import com.projectswg.common.network.packets.PacketType;
import com.projectswg.common.utilities.ByteUtilities;
import com.projectswg.connection.HolocoreSocket;
import com.projectswg.connection.ServerConnectionChangedReason;
import com.projectswg.connection.RawPacket;
import com.projectswg.connection.ServerConnectionChangedReason;
import com.projectswg.forwarder.Forwarder.ForwarderData;
import com.projectswg.forwarder.intents.client.ClientConnectedIntent;
import com.projectswg.forwarder.intents.client.ClientDisconnectedIntent;
@@ -13,20 +15,27 @@ import com.projectswg.forwarder.intents.control.StopForwarderIntent;
import com.projectswg.forwarder.intents.server.ServerConnectedIntent;
import com.projectswg.forwarder.intents.server.ServerDisconnectedIntent;
import com.projectswg.forwarder.resources.networking.NetInterceptor;
import me.joshlarson.jlcommon.concurrency.BasicThread;
import me.joshlarson.jlcommon.concurrency.Delay;
import me.joshlarson.jlcommon.concurrency.ThreadPool;
import me.joshlarson.jlcommon.control.IntentChain;
import me.joshlarson.jlcommon.control.IntentHandler;
import me.joshlarson.jlcommon.control.Service;
import me.joshlarson.jlcommon.log.Log;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ServerConnectionService extends Service {
private final IntentChain intentChain;
private final AtomicReference<Thread> activeThread;
private final AtomicBoolean running;
private final BasicThread thread;
private final ThreadPool thread;
private final Lock runLock;
private final Lock sleepLock;
private HolocoreSocket holocore;
private NetInterceptor interceptor;
@@ -34,16 +43,27 @@ public class ServerConnectionService extends Service {
public ServerConnectionService() {
this.intentChain = new IntentChain();
this.activeThread = new AtomicReference<>(null);
this.running = new AtomicBoolean(false);
this.thread = new BasicThread("server-connection", this::runningLoop);
this.thread = new ThreadPool(2, "server-connection");
this.runLock = new ReentrantLock(true);
this.sleepLock = new ReentrantLock(true);
this.holocore = null;
this.interceptor = null;
this.data = null;
}
@Override
public boolean start() {
thread.start();
return true;
}
@Override
public boolean stop() {
return stopRunningLoop();
running.set(false);
thread.stop(true);
return thread.awaitTermination(1000);
}
@IntentHandler
@@ -59,8 +79,7 @@ public class ServerConnectionService extends Service {
@IntentHandler
private void handleClientConnectedIntent(ClientConnectedIntent cci) {
stopRunningLoop();
thread.start();
queueConnectionLoop(0);
}
@IntentHandler
@@ -72,58 +91,95 @@ public class ServerConnectionService extends Service {
private void handleDataPacketInboundIntent(DataPacketInboundIntent dpii) {
if (running.get())
holocore.send(interceptor.interceptClient(dpii.getData()));
else
Log.w("Dropping packet destined for server: %s", ByteUtilities.getHexString(dpii.getData()));
}
private boolean stopRunningLoop() {
if (running.getAndSet(false)) {
thread.stop(true);
return thread.awaitTermination(500);
private void stopRunningLoop() {
running.set(false);
Thread activeThread = this.activeThread.get();
if (activeThread != null)
activeThread.interrupt();
try {
if (runLock.tryLock(1, TimeUnit.SECONDS))
runLock.unlock();
} catch (InterruptedException e) {
// Ignored
}
return true;
}
private void runningLoop() {
holocore = new HolocoreSocket(data.getAddress().getAddress(), data.getAddress().getPort());
running.set(true);
while (running.get()) {
private void queueConnectionLoop(long delay) {
thread.execute(() -> startConnectionLoop(delay));
}
private void startConnectionLoop(long delay) {
if (sleepLock.tryLock()) {
try {
connectedLoop();
if (!Delay.sleepMilli(delay))
return;
} finally {
sleepLock.unlock();
}
} else if (delay > 0) {
return;
}
if (runLock.tryLock()) {
try {
activeThread.set(Thread.currentThread());
holocore = new HolocoreSocket(data.getAddress().getAddress(), data.getAddress().getPort());
running.set(true);
if (attemptConnection()) {
while (holocore.isConnected()) {
if (!connectionLoop())
break;
}
}
} catch (Throwable t) {
Log.w(t);
Log.i("Disconnected from server. Sleeping 3 seconds");
holocore.disconnect(ServerConnectionChangedReason.UNKNOWN);
Delay.sleepMilli(3000);
queueConnectionLoop(3000);
} finally {
cleanupConnection();
activeThread.set(null);
runLock.unlock();
}
}
Log.t("Destroying holocore connection");
holocore.terminate();
holocore = null;
}
private void connectedLoop() {
private boolean attemptConnection() {
Log.t("Attempting to connect to server at %s", holocore.getRemoteAddress());
if (!holocore.connect(5000)) {
Log.t("Failed to connect to server. Sleeping 3 seconds");
Delay.sleepMilli(3000);
return;
queueConnectionLoop(3000);
return false;
}
intentChain.broadcastAfter(getIntentManager(), new ServerConnectedIntent());
Log.i("Successfully connected to server at %s", holocore.getRemoteAddress());
while (holocore.isConnected()) {
if (!running.get()) {
holocore.disconnect(ServerConnectionChangedReason.CLIENT_DISCONNECT);
break;
}
RawPacket inbound = holocore.receive();
if (inbound == null) {
holocore.disconnect(ServerConnectionChangedReason.SOCKET_CLOSED);
break;
}
intentChain.broadcastAfter(getIntentManager(), new DataPacketOutboundIntent(interceptor.interceptServer(inbound.getData())));
return true;
}
private boolean connectionLoop() {
if (!running.get()) {
holocore.disconnect(ServerConnectionChangedReason.CLIENT_DISCONNECT);
return false;
}
RawPacket inbound = holocore.receive();
if (inbound == null) {
holocore.disconnect(ServerConnectionChangedReason.SOCKET_CLOSED);
return false;
}
intentChain.broadcastAfter(getIntentManager(), new DataPacketOutboundIntent(interceptor.interceptServer(inbound.getData())));
return true;
}
private void cleanupConnection() {
intentChain.broadcastAfter(getIntentManager(), new ServerDisconnectedIntent());
Log.i("Disconnected from server");
holocore.terminate();
holocore = null;
running.set(false);
}
}