mirror of
https://bitbucket.org/projectswg/forwarder.git
synced 2026-01-16 23:04:26 -05:00
Fixed character creation screen loading and the "double enter" bug
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -62,4 +62,9 @@ public class Acknowledge extends Packet {
|
||||
|
||||
public short getSequence() { return sequence; }
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("Acknowledge[%d]", sequence);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,4 +22,9 @@ public class KeepAlive extends Packet {
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("KeepAlive[]");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -112,4 +112,9 @@ public class MultiPacket extends Packet {
|
||||
return length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("MultiPacket[packets=%d]", content.size());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -58,4 +58,10 @@ public class OutOfOrder extends Packet {
|
||||
}
|
||||
|
||||
public short getSequence() { return sequence; }
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("OutOfOrder[%d]", sequence);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user