Fix Ping/Pong (de)serialization and response

This commit is contained in:
sim 2024-12-29 20:42:15 +00:00
parent 117c3f1041
commit 3986cb916f
5 changed files with 44 additions and 9 deletions

View file

@ -30,6 +30,11 @@ object MessageSender {
} }
} }
fun ping(context: Context) {
send(context, ClientMessage.Ping)
ServerConnection.waitingPong.set(true)
}
fun hasPendingMsgs(): Boolean { fun hasPendingMsgs(): Boolean {
return messageQueue.isNotEmpty() return messageQueue.isNotEmpty()
} }

View file

@ -8,7 +8,7 @@ import android.util.Log
import android.widget.Toast import android.widget.Toast
import java.util.Calendar import java.util.Calendar
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
import kotlinx.serialization.json.Json import java.util.concurrent.atomic.AtomicBoolean
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import okhttp3.Response import okhttp3.Response
@ -33,7 +33,6 @@ import org.unifiedpush.distributor.utils.removeSync
class ServerConnection(private val context: Context, private val releaseLock: () -> Unit) : WebSocketListener() { class ServerConnection(private val context: Context, private val releaseLock: () -> Unit) : WebSocketListener() {
private val json = Json { ignoreUnknownKeys = true }
private val store = AppStore(context) private val store = AppStore(context)
fun start(): WebSocket { fun start(): WebSocket {
@ -73,7 +72,7 @@ class ServerConnection(private val context: Context, private val releaseLock: ()
is ServerMessage.Broadcast -> ignoreEvent() is ServerMessage.Broadcast -> ignoreEvent()
is ServerMessage.Hello -> onHello(ws, message) is ServerMessage.Hello -> onHello(ws, message)
is ServerMessage.Notification -> onNotification(ws, message) is ServerMessage.Notification -> onNotification(ws, message)
ServerMessage.Ping -> onPing() ServerMessage.Ping -> onPing(ws)
is ServerMessage.Register -> onRegister(message) is ServerMessage.Register -> onRegister(message)
is ServerMessage.Unegister -> onUnregister(message) is ServerMessage.Unegister -> onUnregister(message)
} }
@ -119,8 +118,14 @@ class ServerConnection(private val context: Context, private val releaseLock: ()
).send(ws) ).send(ws)
} }
private fun onPing() { private fun onPing(ws: WebSocket) {
FailureCounter.newPing(context) FailureCounter.newPing(context)
if (!waitingPong.getAndSet(false)) {
Log.d(TAG, "Sending Pong")
ClientMessage.Ping.send(ws)
} else {
Log.d(TAG, "Received Pong")
}
} }
private fun onRegister(message: ServerMessage.Register) { private fun onRegister(message: ServerMessage.Register) {
@ -201,5 +206,6 @@ class ServerConnection(private val context: Context, private val releaseLock: ()
companion object { companion object {
var lastEventDate: Calendar? = null var lastEventDate: Calendar? = null
var waitingPong = AtomicBoolean(false)
} }
} }

View file

@ -105,8 +105,15 @@ sealed class ClientMessage {
@Serializable @Serializable
data class ClientAck(val channelID: String, val version: String) data class ClientAck(val channelID: String, val version: String)
fun send(ws: WebSocket) { fun serialize(): String {
val json = Json { ignoreUnknownKeys = true } val json = Json { ignoreUnknownKeys = true }
ws.send(json.encodeToString<ClientMessage>(this)) return when (this) {
Ping -> "{}"
else -> json.encodeToString<ClientMessage>(this)
}
}
fun send(ws: WebSocket) {
ws.send(this.serialize())
} }
} }

View file

@ -3,6 +3,8 @@ package org.unifiedpush.distributor.sunup.api.data
import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.SerializationException
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonClassDiscriminator import kotlinx.serialization.json.JsonClassDiscriminator
@OptIn(ExperimentalSerializationApi::class) @OptIn(ExperimentalSerializationApi::class)
@ -97,4 +99,19 @@ sealed class ServerMessage {
@Serializable @Serializable
@SerialName("ping") @SerialName("ping")
data object Ping : ServerMessage() data object Ping : ServerMessage()
companion object {
fun deserialize(jsonStr: String): ServerMessage? {
val json = Json { ignoreUnknownKeys = true }
return try {
json.decodeFromString<ServerMessage>(jsonStr)
} catch (e: SerializationException) {
if (json.decodeFromString<Map<String, String>>(jsonStr).isEmpty()) {
Ping
} else {
null
}
}
}
}
} }

View file

@ -7,7 +7,6 @@ import android.util.Log
import androidx.work.* import androidx.work.*
import org.unifiedpush.distributor.WorkerCompanion import org.unifiedpush.distributor.WorkerCompanion
import org.unifiedpush.distributor.sunup.api.MessageSender import org.unifiedpush.distributor.sunup.api.MessageSender
import org.unifiedpush.distributor.sunup.api.data.ClientMessage
import org.unifiedpush.distributor.sunup.callback.NetworkCallbackFactory import org.unifiedpush.distributor.sunup.callback.NetworkCallbackFactory
import org.unifiedpush.distributor.sunup.utils.TAG import org.unifiedpush.distributor.sunup.utils.TAG
@ -20,15 +19,16 @@ class RestartWorker(ctx: Context, params: WorkerParameters) : Worker(ctx, params
override fun doWork(): Result { override fun doWork(): Result {
// We avoid running twice at the same time // We avoid running twice at the same time
synchronized(lock) { synchronized(lock) {
Log.d(TAG, "Working") Log.d(TAG, "Working [$id]")
if (!NetworkCallbackFactory.hasInternet) { if (!NetworkCallbackFactory.hasInternet) {
Log.d(TAG, "Aborting, no internet.") Log.d(TAG, "Aborting, no internet.")
return Result.success() return Result.success()
} }
if (FailureCounter.isRunningWithoutFailure) { if (FailureCounter.isRunningWithoutFailure) {
Log.d(TAG, "Running without failure")
// We send a ping, if it fails it will restart this worker, and wont // We send a ping, if it fails it will restart this worker, and wont
// pass this check // pass this check
MessageSender.send(applicationContext, ClientMessage.Ping) MessageSender.ping(applicationContext)
return Result.success() return Result.success()
} }
Log.d(TAG, "Restarting") Log.d(TAG, "Restarting")