mirror of
https://github.com/ProjectSWGCore/forwarder.git
synced 2026-09-13 00:45:00 -04:00
Added 1s heartbeat and 5s timeout for the connection
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user