Simple rate limiting of RS sending
This commit is contained in:
parent
401e8e6712
commit
56dac76ca8
|
@ -25,6 +25,9 @@ import im.vector.app.features.settings.VectorPreferences
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.SupervisorJob
|
import kotlinx.coroutines.SupervisorJob
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||||
|
import kotlinx.coroutines.flow.catch
|
||||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
|
@ -52,10 +55,43 @@ class AutoRageShaker @Inject constructor(
|
||||||
private val uisiDetectors = mutableMapOf<String, UISIDetector>()
|
private val uisiDetectors = mutableMapOf<String, UISIDetector>()
|
||||||
private var currentActiveSessionId: String? = null
|
private var currentActiveSessionId: String? = null
|
||||||
|
|
||||||
|
// Simple in memory cache of already sent report
|
||||||
|
private data class ReportInfo(
|
||||||
|
val roomId: String,
|
||||||
|
val sessionId: String
|
||||||
|
)
|
||||||
|
|
||||||
|
private val alreadyReportedUisi = mutableListOf<ReportInfo>()
|
||||||
|
|
||||||
|
private val e2eDetectedFlow = MutableSharedFlow<E2EMessageDetected>(replay = 0)
|
||||||
|
private val matchingRSRequestFlow = MutableSharedFlow<Event>(replay = 0)
|
||||||
|
|
||||||
fun initialize() {
|
fun initialize() {
|
||||||
observeActiveSession()
|
observeActiveSession()
|
||||||
// It's a singleton...
|
// It's a singleton...
|
||||||
vectorPreferences.subscribeToChanges(this)
|
vectorPreferences.subscribeToChanges(this)
|
||||||
|
|
||||||
|
// Simple rate limit, notice that order is not
|
||||||
|
// necessarily preserved
|
||||||
|
e2eDetectedFlow
|
||||||
|
.onEach {
|
||||||
|
sendRageShake(it)
|
||||||
|
delay(2_000)
|
||||||
|
}
|
||||||
|
.catch { cause ->
|
||||||
|
Timber.w(cause, "Failed to RS")
|
||||||
|
}
|
||||||
|
.launchIn(coroutineScope)
|
||||||
|
|
||||||
|
matchingRSRequestFlow
|
||||||
|
.onEach {
|
||||||
|
sendMatchingRageShake(it)
|
||||||
|
delay(2_000)
|
||||||
|
}
|
||||||
|
.catch { cause ->
|
||||||
|
Timber.w(cause, "Failed to send matching rageshake")
|
||||||
|
}
|
||||||
|
.launchIn(coroutineScope)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
|
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
|
||||||
|
@ -83,63 +119,83 @@ class AutoRageShaker @Inject constructor(
|
||||||
fun decryptionErrorDetected(target: E2EMessageDetected) {
|
fun decryptionErrorDetected(target: E2EMessageDetected) {
|
||||||
if (target.source == UISIEventSource.INITIAL_SYNC) return
|
if (target.source == UISIEventSource.INITIAL_SYNC) return
|
||||||
if (activeSessionHolder.getSafeActiveSession()?.sessionId != currentActiveSessionId) return
|
if (activeSessionHolder.getSafeActiveSession()?.sessionId != currentActiveSessionId) return
|
||||||
coroutineScope.launch {
|
val shouldSendRS = synchronized(alreadyReportedUisi) {
|
||||||
bugReporter.sendBugReport(
|
val reportInfo = ReportInfo(target.roomId, target.sessionId)
|
||||||
context = context,
|
val alreadySent = alreadyReportedUisi.contains(reportInfo)
|
||||||
reportType = ReportType.AUTO_UISI,
|
if (!alreadySent) {
|
||||||
withDevicesLogs = true,
|
alreadyReportedUisi.add(reportInfo)
|
||||||
withCrashLogs = true,
|
}
|
||||||
withKeyRequestHistory = true,
|
!alreadySent
|
||||||
withScreenshot = false,
|
}
|
||||||
theBugDescription = "UISI detected",
|
if (shouldSendRS) {
|
||||||
serverVersion = "",
|
coroutineScope.launch {
|
||||||
canContact = false,
|
e2eDetectedFlow.emit(target)
|
||||||
customFields = mapOf("auto-uisi" to buildString {
|
}
|
||||||
append("\neventId: ${target.eventId}")
|
}
|
||||||
append("\nroomId: ${target.roomId}")
|
}
|
||||||
append("\nsenderKey: ${target.senderKey}")
|
|
||||||
append("\nsource: ${target.source}")
|
private fun sendRageShake(target: E2EMessageDetected) {
|
||||||
append("\ndeviceId: ${target.senderDeviceId}")
|
bugReporter.sendBugReport(
|
||||||
append("\nuserId: ${target.senderUserId}")
|
context = context,
|
||||||
append("\nsessionId: ${target.sessionId}")
|
reportType = ReportType.AUTO_UISI,
|
||||||
}),
|
withDevicesLogs = true,
|
||||||
listener = object : BugReporter.IMXBugReportListener {
|
withCrashLogs = true,
|
||||||
override fun onUploadCancelled() {
|
withKeyRequestHistory = true,
|
||||||
|
withScreenshot = false,
|
||||||
|
theBugDescription = "UISI detected",
|
||||||
|
serverVersion = "",
|
||||||
|
canContact = false,
|
||||||
|
customFields = mapOf("auto-uisi" to buildString {
|
||||||
|
append("\neventId: ${target.eventId}")
|
||||||
|
append("\nroomId: ${target.roomId}")
|
||||||
|
append("\nsenderKey: ${target.senderKey}")
|
||||||
|
append("\nsource: ${target.source}")
|
||||||
|
append("\ndeviceId: ${target.senderDeviceId}")
|
||||||
|
append("\nuserId: ${target.senderUserId}")
|
||||||
|
append("\nsessionId: ${target.sessionId}")
|
||||||
|
}),
|
||||||
|
listener = object : BugReporter.IMXBugReportListener {
|
||||||
|
override fun onUploadCancelled() {
|
||||||
|
synchronized(alreadyReportedUisi) {
|
||||||
|
alreadyReportedUisi.remove(ReportInfo(target.roomId, target.sessionId))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onUploadFailed(reason: String?) {
|
override fun onUploadFailed(reason: String?) {
|
||||||
|
synchronized(alreadyReportedUisi) {
|
||||||
|
alreadyReportedUisi.remove(ReportInfo(target.roomId, target.sessionId))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onProgress(progress: Int) {
|
override fun onProgress(progress: Int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onUploadSucceed(reportUrl: String?) {
|
override fun onUploadSucceed(reportUrl: String?) {
|
||||||
Timber.w("## VALR Report URL is $reportUrl")
|
Timber.w("## VALR Report URL is $reportUrl")
|
||||||
// we need to send the toDevice message to the sender
|
// we need to send the toDevice message to the sender
|
||||||
|
|
||||||
coroutineScope.launch {
|
coroutineScope.launch {
|
||||||
try {
|
try {
|
||||||
activeSessionHolder.getSafeActiveSession()?.sendToDevice(
|
activeSessionHolder.getSafeActiveSession()?.sendToDevice(
|
||||||
eventType = AUTO_RS_REQUEST,
|
eventType = AUTO_RS_REQUEST,
|
||||||
userId = target.senderUserId,
|
userId = target.senderUserId,
|
||||||
deviceId = target.senderDeviceId,
|
deviceId = target.senderDeviceId,
|
||||||
content = mapOf(
|
content = mapOf(
|
||||||
"event_id" to target.eventId,
|
"event_id" to target.eventId,
|
||||||
"room_id" to target.roomId,
|
"room_id" to target.roomId,
|
||||||
"session_id" to target.sessionId,
|
"session_id" to target.sessionId,
|
||||||
"device_id" to target.senderDeviceId,
|
"device_id" to target.senderDeviceId,
|
||||||
"user_id" to target.senderUserId,
|
"user_id" to target.senderUserId,
|
||||||
"sender_key" to target.senderKey,
|
"sender_key" to target.senderKey,
|
||||||
"matching_issue" to reportUrl
|
"matching_issue" to reportUrl
|
||||||
).toContent()
|
).toContent()
|
||||||
)
|
)
|
||||||
} catch (failure: Throwable) {
|
} catch (failure: Throwable) {
|
||||||
Timber.w("## VALR : failed to send auto-uisi to device")
|
Timber.w("## VALR : failed to send auto-uisi to device")
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fun remoteAutoUISIRequest(event: Event) {
|
fun remoteAutoUISIRequest(event: Event) {
|
||||||
|
@ -147,40 +203,44 @@ class AutoRageShaker @Inject constructor(
|
||||||
if (activeSessionHolder.getSafeActiveSession()?.sessionId != currentActiveSessionId) return
|
if (activeSessionHolder.getSafeActiveSession()?.sessionId != currentActiveSessionId) return
|
||||||
|
|
||||||
coroutineScope.launch {
|
coroutineScope.launch {
|
||||||
val eventId = event.content?.get("event_id")
|
matchingRSRequestFlow.emit(event)
|
||||||
val roomId = event.content?.get("room_id")
|
|
||||||
val sessionId = event.content?.get("session_id")
|
|
||||||
val deviceId = event.content?.get("device_id")
|
|
||||||
val userId = event.content?.get("user_id")
|
|
||||||
val senderKey = event.content?.get("sender_key")
|
|
||||||
val matchingIssue = event.content?.get("matching_issue")?.toString() ?: ""
|
|
||||||
|
|
||||||
bugReporter.sendBugReport(
|
|
||||||
context = context,
|
|
||||||
reportType = ReportType.AUTO_UISI_SENDER,
|
|
||||||
withDevicesLogs = true,
|
|
||||||
withCrashLogs = true,
|
|
||||||
withKeyRequestHistory = true,
|
|
||||||
withScreenshot = false,
|
|
||||||
theBugDescription = "UISI detected $matchingIssue",
|
|
||||||
serverVersion = "",
|
|
||||||
canContact = false,
|
|
||||||
customFields = mapOf(
|
|
||||||
"auto-uisi" to buildString {
|
|
||||||
append("\neventId: $eventId")
|
|
||||||
append("\nroomId: $roomId")
|
|
||||||
append("\nsenderKey: $senderKey")
|
|
||||||
append("\ndeviceId: $deviceId")
|
|
||||||
append("\nuserId: $userId")
|
|
||||||
append("\nsessionId: $sessionId")
|
|
||||||
},
|
|
||||||
"matching_issue" to matchingIssue
|
|
||||||
),
|
|
||||||
listener = null
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun sendMatchingRageShake(event: Event) {
|
||||||
|
val eventId = event.content?.get("event_id")
|
||||||
|
val roomId = event.content?.get("room_id")
|
||||||
|
val sessionId = event.content?.get("session_id")
|
||||||
|
val deviceId = event.content?.get("device_id")
|
||||||
|
val userId = event.content?.get("user_id")
|
||||||
|
val senderKey = event.content?.get("sender_key")
|
||||||
|
val matchingIssue = event.content?.get("matching_issue")?.toString() ?: ""
|
||||||
|
|
||||||
|
bugReporter.sendBugReport(
|
||||||
|
context = context,
|
||||||
|
reportType = ReportType.AUTO_UISI_SENDER,
|
||||||
|
withDevicesLogs = true,
|
||||||
|
withCrashLogs = true,
|
||||||
|
withKeyRequestHistory = true,
|
||||||
|
withScreenshot = false,
|
||||||
|
theBugDescription = "UISI detected $matchingIssue",
|
||||||
|
serverVersion = "",
|
||||||
|
canContact = false,
|
||||||
|
customFields = mapOf(
|
||||||
|
"auto-uisi" to buildString {
|
||||||
|
append("\neventId: $eventId")
|
||||||
|
append("\nroomId: $roomId")
|
||||||
|
append("\nsenderKey: $senderKey")
|
||||||
|
append("\ndeviceId: $deviceId")
|
||||||
|
append("\nuserId: $userId")
|
||||||
|
append("\nsessionId: $sessionId")
|
||||||
|
},
|
||||||
|
"matching_issue" to matchingIssue
|
||||||
|
),
|
||||||
|
listener = null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
private val detector = UISIDetector().apply {
|
private val detector = UISIDetector().apply {
|
||||||
callback = object : UISIDetector.UISIDetectorCallback {
|
callback = object : UISIDetector.UISIDetectorCallback {
|
||||||
override val reciprocateToDeviceEventType: String
|
override val reciprocateToDeviceEventType: String
|
||||||
|
|
Loading…
Reference in New Issue