diff --git a/src/main/java/com/projectswg/forwarder/resources/server/HolocoreConnection.kt b/src/main/java/com/projectswg/forwarder/resources/server/HolocoreConnection.kt index 96574bc..92ea9bc 100644 --- a/src/main/java/com/projectswg/forwarder/resources/server/HolocoreConnection.kt +++ b/src/main/java/com/projectswg/forwarder/resources/server/HolocoreConnection.kt @@ -79,6 +79,13 @@ class HolocoreConnection(private val intentManager: IntentManager, this.disconnectReason.set(reason) } + fun ping() { + val currentTime = System.nanoTime() + val dataBuffer = NetBuffer.allocate(8) + dataBuffer.addLong(currentTime) + wsProtocol.send(WebsocketFrame(WebsocketFrameType.PING, dataBuffer.buffer.array())) + } + fun sendPacket(packet: ByteArray) { val bb = ByteBuffer.wrap(packet).order(ByteOrder.LITTLE_ENDIAN) @@ -243,6 +250,16 @@ class HolocoreConnection(private val intentManager: IntentManager, connectionStatus.set(ServerConnectionStatus.DISCONNECTED) } + override fun onPong(obj: WebSocketHandler, data: ByteArray?) { + val currentTime = System.nanoTime() + data ?: return + if (data.size != 8) + return + val dataBuffer = NetBuffer.wrap(data) + val sendTime = dataBuffer.long + Log.d("Received pong. RTT: %dus", (currentTime - sendTime) / 1000) + } + override fun onBinaryMessage(obj: WebSocketHandler, rawData: ByteArray) { val dataBuffer = NetBuffer.wrap(rawData) dataBuffer.short diff --git a/src/main/kotlin/com/projectswg/forwarder/services/server/ServerConnectionService.kt b/src/main/kotlin/com/projectswg/forwarder/services/server/ServerConnectionService.kt index 519c37b..7245312 100644 --- a/src/main/kotlin/com/projectswg/forwarder/services/server/ServerConnectionService.kt +++ b/src/main/kotlin/com/projectswg/forwarder/services/server/ServerConnectionService.kt @@ -6,6 +6,7 @@ import com.projectswg.forwarder.intents.* import com.projectswg.forwarder.resources.networking.NetInterceptor import com.projectswg.forwarder.resources.server.HolocoreConnection import me.joshlarson.jlcommon.concurrency.BasicThread +import me.joshlarson.jlcommon.concurrency.ScheduledThreadPool import me.joshlarson.jlcommon.control.IntentHandler import me.joshlarson.jlcommon.control.Service import me.joshlarson.jlcommon.log.Log @@ -13,15 +14,26 @@ import java.util.concurrent.atomic.AtomicReference class ServerConnectionService : Service() { - private val thread: BasicThread = BasicThread("server-connection") { this.primaryConnectionLoop() } + private val thread = BasicThread("server-connection") { this.primaryConnectionLoop() } + private val keepAliveThread = ScheduledThreadPool(1, "server-keepalive") private val currentConnection = AtomicReference(null) private lateinit var interceptor: NetInterceptor // set by StartForwarderIntent private lateinit var data: ForwarderData // set by StartForwarderIntent + override fun start(): Boolean { + keepAliveThread.start() + keepAliveThread.executeWithFixedDelay(30_000, 30_000) { currentConnection.get()?.ping() } + return super.start() + } + override fun stop(): Boolean { - return stopRunningLoop(HoloConnectionStopped.ConnectionStoppedReason.APPLICATION) + keepAliveThread.stop() + val stoppedKeepAlive = keepAliveThread.awaitTermination(1000); + val stoppedServerConnection = stopRunningLoop(HoloConnectionStopped.ConnectionStoppedReason.APPLICATION) + + return stoppedKeepAlive && stoppedServerConnection } @IntentHandler