From d26b78c92a1094f4ad8bdad2bdb0b37d1debad08 Mon Sep 17 00:00:00 2001 From: Obique PSWG Date: Sat, 8 Aug 2015 16:56:56 -0500 Subject: [PATCH] Fixed connecting to galaxy where some packets aren't received at all --- src/network/NetworkClient.java | 4 ++ src/network/NetworkProtocol.java | 5 +++ src/network/OutboundNetworkHandler.java | 30 +++++++++++++++ .../network/NetworkClientManager.java | 38 ++++++++++++++++++- 4 files changed, 76 insertions(+), 1 deletion(-) diff --git a/src/network/NetworkClient.java b/src/network/NetworkClient.java index 7102e85f..72d80590 100644 --- a/src/network/NetworkClient.java +++ b/src/network/NetworkClient.java @@ -67,6 +67,10 @@ public class NetworkClient { connId = 0; } + public void resendOldUnacknowledged() { + protocol.resendOldUnacknowledged(); + } + public void setCrc(int crc) { protocol.setCrc(crc); } diff --git a/src/network/NetworkProtocol.java b/src/network/NetworkProtocol.java index e2c95a9b..4e76384e 100644 --- a/src/network/NetworkProtocol.java +++ b/src/network/NetworkProtocol.java @@ -91,6 +91,11 @@ public class NetworkProtocol implements InboundEventCallback { outbound.reset(); } + public void resendOldUnacknowledged() { + outbound.resendOldUnacknowledged(); + flushAssembled(); + } + public List process(byte [] data) { inbound.onReceive(data); List packets = new LinkedList(); diff --git a/src/network/OutboundNetworkHandler.java b/src/network/OutboundNetworkHandler.java index 356d6b0a..cfad5a4e 100644 --- a/src/network/OutboundNetworkHandler.java +++ b/src/network/OutboundNetworkHandler.java @@ -30,6 +30,7 @@ package network; import java.util.Iterator; import java.util.LinkedList; import java.util.Queue; +import java.util.concurrent.TimeUnit; import resources.SortedLinkedList; import network.encryption.Encryption; @@ -43,6 +44,8 @@ import network.packets.swg.SWGPacket; public class OutboundNetworkHandler { + private static final long RESEND_TIMEOUT = TimeUnit.MILLISECONDS.toMillis(3000); + private final Queue assembleQueue; private final SortedLinkedList sequenced; private short sendSequence; @@ -104,6 +107,7 @@ public class OutboundNetworkHandler { } else if (!sp.isSent() || sp.getSequence() == sequence) { pushAssembledUnencrypted(sp.getPacket()); // Pre-encrypted before putting into list sp.setSent(true); + sp.updateSent(); } } } @@ -121,6 +125,18 @@ public class OutboundNetworkHandler { } } + public synchronized void resendOldUnacknowledged() { + synchronized (sequenced) { + for (SequencedPacket packet : sequenced) { + if (packet.hasBeen(RESEND_TIMEOUT)) { + pushAssembledUnencrypted(packet.getPacket()); // Pre-encrypted before putting into list + packet.setSent(true); + packet.updateSent(); + } + } + } + } + private byte [] pushAssembledEncrypted(byte [] data) { data = Encryption.encode(data, crc); synchronized (assembleQueue) { @@ -229,11 +245,13 @@ public class OutboundNetworkHandler { private static class SequencedPacket implements Comparable { private final short sequence; private final byte [] packet; + private long sentTime; private boolean sent; public SequencedPacket(short sequence, byte [] packet) { this.sequence = sequence; this.packet = packet; + this.sentTime = System.nanoTime(); sent = false; } @@ -253,6 +271,18 @@ public class OutboundNetworkHandler { this.sent = sent; } + public boolean hasBeen(double milliseconds) { + return hasBeen() >= milliseconds; + } + + public double hasBeen() { + return (System.nanoTime() - sentTime) / 1E6; + } + + public void updateSent() { + sentTime = System.nanoTime(); + } + @Override public int compareTo(SequencedPacket sp) { if (sequence < sp.getSequence()) diff --git a/src/services/network/NetworkClientManager.java b/src/services/network/NetworkClientManager.java index 00b77396..5279a9d7 100644 --- a/src/services/network/NetworkClientManager.java +++ b/src/services/network/NetworkClientManager.java @@ -42,6 +42,8 @@ import java.util.Queue; import java.util.Random; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; import network.NetworkClient; import network.PacketReceiver; @@ -56,16 +58,20 @@ import resources.control.Intent; import resources.control.Manager; import resources.network.ServerType; import resources.network.UDPServer.UDPPacket; +import resources.server_info.Log; +import utilities.ThreadUtilities; public class NetworkClientManager extends Manager implements PacketReceiver { private final Map > clients; private final Map networkClients; private final Queue receivedPackets; + private final ScheduledExecutorService packetResender; private final ExecutorService packetProcessor; private final Random crcGenerator; private final PacketSender packetSender; private final Runnable processPacketRunnable; + private final Runnable packetResendRunnable; private long networkId; public NetworkClientManager(PacketSender packetSender) { @@ -73,7 +79,8 @@ public class NetworkClientManager extends Manager implements PacketReceiver { clients = new HashMap>(); networkClients = new HashMap(); receivedPackets = new LinkedList<>(); - packetProcessor = Executors.newCachedThreadPool(); + packetResender = Executors.newSingleThreadScheduledExecutor(ThreadUtilities.newThreadFactory("packet-resender")); + packetProcessor = Executors.newCachedThreadPool(ThreadUtilities.newThreadFactory("packet-processor-%d")); crcGenerator = new Random(); processPacketRunnable = new Runnable() { public void run() { @@ -85,6 +92,11 @@ public class NetworkClientManager extends Manager implements PacketReceiver { } } }; + packetResendRunnable = new Runnable() { + public void run() { + resendOldUnacknowledged(); + } + }; networkId = 0; } @@ -93,6 +105,7 @@ public class NetworkClientManager extends Manager implements PacketReceiver { registerForIntent(InboundPacketIntent.TYPE); registerForIntent(OutboundPacketIntent.TYPE); registerForIntent(CloseConnectionIntent.TYPE); + packetResender.scheduleAtFixedRate(packetResendRunnable, 0, 200, TimeUnit.MILLISECONDS); return super.initialize(); } @@ -104,6 +117,20 @@ public class NetworkClientManager extends Manager implements PacketReceiver { return super.stop(); } + @Override + public boolean terminate() { + packetProcessor.shutdownNow(); + packetResender.shutdownNow(); + boolean success = true; + try { + success = packetProcessor.awaitTermination(5, TimeUnit.SECONDS); + success = packetResender.awaitTermination(5, TimeUnit.SECONDS) && success; + } catch (InterruptedException e) { + e.printStackTrace(); + } + return super.terminate() && success; + } + @Override public void receivePacket(ServerType type, UDPPacket packet) { synchronized (receivedPackets) { @@ -166,6 +193,15 @@ public class NetworkClientManager extends Manager implements PacketReceiver { return crc; } + private void resendOldUnacknowledged() { + synchronized (clients) { + for (NetworkClient client : networkClients.values()) { + client.resendOldUnacknowledged(); + flushPackets(); + } + } + } + private void handleOutboundPacket(long networkId, Packet p) { synchronized (clients) { NetworkClient client = networkClients.get(networkId);