Added 1s heartbeat and 5s timeout for the connection

This commit is contained in:
Josh Larson
2016-01-03 04:02:32 -06:00
parent f977d90093
commit 03ba295570
4 changed files with 86 additions and 4 deletions
+22 -1
View File
@@ -1,18 +1,25 @@
package com.projectswg;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import com.projectswg.ClientReceiver.ClientReceiverCallback;
import com.projectswg.ClientReceiver.ConnectionState;
import com.projectswg.networking.NetInterceptor;
import com.projectswg.networking.swg.HeartBeat;
public class ClientConnection {
private ScheduledExecutorService pinger;
private ClientSender sender;
private ClientReceiver receiver;
private ClientCallback callback;
private NetInterceptor interceptor;
private boolean connected;
public ClientConnection(int loginPort, int zonePort) {
this.callback = null;
callback = null;
connected = false;
interceptor = new NetInterceptor();
sender = new ClientSender(interceptor, loginPort, zonePort);
receiver = new ClientReceiver(interceptor);
@@ -31,9 +38,12 @@ public class ClientConnection {
public void onConnected() { ClientConnection.this.onConnected(); }
public void onConnectionChanged(ConnectionState state) { ClientConnection.this.onConnectionStateChanged(state); }
});
pinger = Executors.newSingleThreadScheduledExecutor();
pinger.scheduleAtFixedRate(()->ping(), 0, 1000, TimeUnit.MILLISECONDS);
}
public void stop() {
pinger.shutdownNow();
sender.stop();
receiver.stop();
if (callback != null)
@@ -54,6 +64,7 @@ public class ClientConnection {
}
private void onDisconnected() {
connected = false;
if (callback != null)
callback.onDisconnected();
sender.reset();
@@ -61,6 +72,7 @@ public class ClientConnection {
}
private void onConnected() {
connected = true;
if (callback != null)
callback.onConnected();
sender.reset();
@@ -80,6 +92,15 @@ public class ClientConnection {
}
}
private void ping() {
if (!connected)
return;
if (receiver.getTimeSinceLastPacket() > 5000)
onDisconnected();
else
sender.send(new HeartBeat().encode().array());
}
public interface ClientCallback {
void onConnected();
void onDisconnected();
+11 -2
View File
@@ -5,6 +5,7 @@ import java.nio.ByteOrder;
import java.util.Arrays;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicLong;
import com.projectswg.networking.NetInterceptor;
import com.projectswg.networking.UDPServer.UDPPacket;
@@ -27,6 +28,7 @@ public class ClientReceiver {
private static final int MAX_PACKET_SIZE = 496;
private final NetInterceptor interceptor;
private final AtomicLong lastPacket;
private ExecutorService executor;
private ClientSender sender;
private ClientReceiverCallback callback;
@@ -37,6 +39,7 @@ public class ClientReceiver {
public ClientReceiver(NetInterceptor interceptor) {
this.interceptor = interceptor;
this.lastPacket = new AtomicLong(0);
setConnectionState(ConnectionState.DISCONNECTED);
sender = null;
callback = null;
@@ -65,11 +68,16 @@ public class ClientReceiver {
rxSequence = -1;
}
public double getTimeSinceLastPacket() {
return (System.nanoTime() - lastPacket.get()) / 1E6;
}
public void onPacket(boolean zone, UDPPacket packet) {
if (packet.getData().length < 2)
return;
if (zone && packet.getData().length == 4) { // Ping
sender.sendRaw(packet.getPort(), packet.getAddress(), packet.getData());
lastPacket.set(System.nanoTime());
return;
}
ByteBuffer data = ByteBuffer.wrap(packet.getData()).order(ByteOrder.BIG_ENDIAN);
@@ -79,10 +87,12 @@ public class ClientReceiver {
this.port = packet.getPort();
sender.setZone(zone);
sender.setPort(packet.getPort());
lastPacket.set(System.nanoTime());
process(data);
} else {
if (packet.getPort() != port || port == 0)
return;
lastPacket.set(System.nanoTime());
executor.submit(() -> {
process(ByteBuffer.wrap(Encryption.decode(data.array(), 0)).order(ByteOrder.BIG_ENDIAN));
});
@@ -193,11 +203,10 @@ public class ClientReceiver {
}
private void onOutOfOrder(OutOfOrder ooo) {
System.out.println("OOO " + ooo.getSequence());
}
private void onAcknowledge(Acknowledge ack) {
System.out.println("ACK " + ack.getSequence());
sender.onAcknowledge(ack.getSequence());
}
+1 -1
View File
@@ -103,7 +103,7 @@ public class ClientSender {
public void disconnect(DisconnectReason reason) {
if (connectionId != -1)
sendRaw(new Disconnect(connectionId, reason).encode().array());
send(new Disconnect(connectionId, reason));
connectionId = -1;
}
@@ -0,0 +1,52 @@
/***********************************************************************************
* 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.networking.swg;
import java.nio.ByteBuffer;
import com.projectswg.networking.SWGPacket;
public class HeartBeat extends SWGPacket {
public static final int CRC = com.projectswg.networking.encryption.CRC.getCrc("HeartBeat");
public HeartBeat() {
}
public void decode(ByteBuffer data) {
super.decode(data, CRC);
}
public ByteBuffer encode() {
ByteBuffer data = ByteBuffer.allocate(6);
addShort(data, 1);
addInt( data, CRC);
return data;
}
}