Add Receive support for the new CallLogEvent proto messages.

This commit is contained in:
Alex Hart
2023-07-19 12:02:53 -03:00
committed by Nicholas
parent 461875b0e4
commit a8349671d0
8 changed files with 260 additions and 20 deletions

View File

@@ -10,6 +10,7 @@ import org.signal.core.util.delete
import org.signal.core.util.insertInto
import org.signal.core.util.logging.Log
import org.signal.core.util.readToList
import org.signal.core.util.readToSet
import org.signal.core.util.readToSingleInt
import org.signal.core.util.readToSingleObject
import org.signal.core.util.requireBlob
@@ -226,6 +227,16 @@ class CallLinkTable(context: Context, databaseHelper: SignalDatabase) : Database
}
}
fun deleteNonAdminCallLinksOnOrBefore(timestamp: Long) {
writableDatabase.withinTransaction { db ->
db.delete(TABLE_NAME)
.where("EXISTS (SELECT 1 FROM ${CallTable.TABLE_NAME} WHERE ${CallTable.TIMESTAMP} <= ? AND ${CallTable.PEER} = $RECIPIENT_ID)", timestamp)
.run()
SignalDatabase.calls.updateAdHocCallEventDeletionTimestamps(skipSync = true)
}
}
fun getAdminCallLinks(roomIds: Set<CallLinkRoomId>): Set<CallLink> {
val queries = SqlUtil.buildCollectionQuery(ROOM_ID, roomIds)
@@ -274,6 +285,18 @@ class CallLinkTable(context: Context, databaseHelper: SignalDatabase) : Database
}
}
fun getAdminCallLinkCredentialsOnOrBefore(timestamp: Long): Set<CallLinkCredentials> {
val query = """
SELECT $ROOT_KEY, $ADMIN_KEY FROM $TABLE_NAME
INNER JOIN ${CallTable.TABLE_NAME} ON ${CallTable.TABLE_NAME}.${CallTable.PEER} = $TABLE_NAME.$RECIPIENT_ID
WHERE ${CallTable.TIMESTAMP} <= $timestamp AND $ADMIN_KEY IS NOT NULL AND $REVOKED = 0
""".trimIndent()
return readableDatabase.query(query).readToSet {
CallLinkCredentials(it.requireNonNullBlob(ROOT_KEY), it.requireNonNullBlob(ADMIN_KEY))
}
}
private fun queryCallLinks(query: String?, offset: Int, limit: Int, asCount: Boolean): Cursor {
//language=sql
val noCallEvent = """

View File

@@ -56,7 +56,7 @@ class CallTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTabl
const val TYPE = "type"
private const val DIRECTION = "direction"
const val EVENT = "event"
private const val TIMESTAMP = "timestamp"
const val TIMESTAMP = "timestamp"
private const val RINGER = "ringer"
private const val DELETION_TIMESTAMP = "deletion_timestamp"
@@ -227,7 +227,7 @@ class CallTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTabl
* If a call link has been revoked, or if we do not have a CallLink table entry for an AD_HOC_CALL type
* event, we mark it deleted.
*/
fun updateAdHocCallEventDeletionTimestamps() {
fun updateAdHocCallEventDeletionTimestamps(skipSync: Boolean = false) {
//language=sql
val statement = """
UPDATE $TABLE_NAME
@@ -245,7 +245,10 @@ class CallTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTabl
Call.deserialize(it)
}.toSet()
CallSyncEventJob.enqueueDeleteSyncEvents(toSync)
if (!skipSync) {
CallSyncEventJob.enqueueDeleteSyncEvents(toSync)
}
ApplicationDependencies.getDeletedCallEventManager().scheduleIfNecessary()
ApplicationDependencies.getDatabaseObserver().notifyCallUpdateObservers()
}
@@ -254,7 +257,7 @@ class CallTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTabl
* If a non-ad-hoc call has been deleted from the message database, then we need to
* set its deletion_timestamp to now.
*/
fun updateCallEventDeletionTimestamps() {
fun updateCallEventDeletionTimestamps(skipSync: Boolean = false) {
val where = "$TYPE != ? AND $DELETION_TIMESTAMP = 0 AND $MESSAGE_ID IS NULL"
val type = Type.serialize(Type.AD_HOC_CALL)
@@ -281,7 +284,10 @@ class CallTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTabl
result
}
CallSyncEventJob.enqueueDeleteSyncEvents(toSync)
if (!skipSync) {
CallSyncEventJob.enqueueDeleteSyncEvents(toSync)
}
ApplicationDependencies.getDeletedCallEventManager().scheduleIfNecessary()
ApplicationDependencies.getDatabaseObserver().notifyCallUpdateObservers()
}
@@ -800,6 +806,20 @@ class CallTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTabl
.run()
}
fun deleteNonAdHocCallEventsOnOrBefore(timestamp: Long) {
val messageIdsOnOrBeforeTimestamp = """
SELECT $MESSAGE_ID FROM $TABLE_NAME WHERE $TIMESTAMP <= $timestamp AND $MESSAGE_ID IS NOT NULL
""".trimIndent()
writableDatabase.withinTransaction { db ->
db.delete(MessageTable.TABLE_NAME)
.where("${MessageTable.ID} IN ($messageIdsOnOrBeforeTimestamp)")
.run()
updateCallEventDeletionTimestamps(skipSync = true)
}
}
fun deleteNonAdHocCallEvents(callRowIds: Set<Long>) {
val messageIds = getMessageIds(callRowIds)
SignalDatabase.messages.deleteCallUpdates(messageIds)

View File

@@ -108,6 +108,7 @@ import org.whispersystems.signalservice.internal.push.SignalServiceProtos.StoryM
import org.whispersystems.signalservice.internal.push.SignalServiceProtos.SyncMessage
import org.whispersystems.signalservice.internal.push.SignalServiceProtos.SyncMessage.Blocked
import org.whispersystems.signalservice.internal.push.SignalServiceProtos.SyncMessage.CallLinkUpdate
import org.whispersystems.signalservice.internal.push.SignalServiceProtos.SyncMessage.CallLogEvent
import org.whispersystems.signalservice.internal.push.SignalServiceProtos.SyncMessage.Configuration
import org.whispersystems.signalservice.internal.push.SignalServiceProtos.SyncMessage.FetchLatest
import org.whispersystems.signalservice.internal.push.SignalServiceProtos.SyncMessage.MessageRequestResponse
@@ -150,6 +151,7 @@ object SyncMessageProcessor {
syncMessage.hasContacts() -> handleSynchronizeContacts(syncMessage.contacts, envelope.timestamp)
syncMessage.hasCallEvent() -> handleSynchronizeCallEvent(syncMessage.callEvent, envelope.timestamp)
syncMessage.hasCallLinkUpdate() -> handleSynchronizeCallLink(syncMessage.callLinkUpdate, envelope.timestamp)
syncMessage.hasCallLogEvent() -> handleSynchronizeCallLogEvent(syncMessage.callLogEvent, envelope.timestamp)
else -> warn(envelope.timestamp, "Contains no known sync types...")
}
}
@@ -1162,6 +1164,16 @@ object SyncMessageProcessor {
}
}
private fun handleSynchronizeCallLogEvent(callLogEvent: CallLogEvent, envelopeTimestamp: Long) {
if (callLogEvent.type != CallLogEvent.Type.CLEAR) {
log(envelopeTimestamp, "Synchronize call log event has an invalid type ${callLogEvent.type}, ignoring.")
return
}
SignalDatabase.calls.deleteNonAdHocCallEventsOnOrBefore(callLogEvent.timestamp)
SignalDatabase.callLinks.deleteNonAdminCallLinksOnOrBefore(callLogEvent.timestamp)
}
private fun handleSynchronizeCallLink(callLinkUpdate: CallLinkUpdate, envelopeTimestamp: Long) {
if (!callLinkUpdate.hasRootKey()) {
log(envelopeTimestamp, "Synchronize call link missing root key, ignoring.")
@@ -1185,21 +1197,20 @@ object SyncMessageProcessor {
callLinkUpdate.adminPassKey?.toByteArray()
)
)
return
}
SignalDatabase.callLinks.insertCallLink(
CallLinkTable.CallLink(
recipientId = RecipientId.UNKNOWN,
roomId = roomId,
credentials = CallLinkCredentials(
linkKeyBytes = callLinkRootKey.keyBytes,
adminPassBytes = callLinkUpdate.adminPassKey?.toByteArray()
),
state = SignalCallLinkState()
} else {
log(envelopeTimestamp, "Synchronize call link for a link we do not know about. Inserting.")
SignalDatabase.callLinks.insertCallLink(
CallLinkTable.CallLink(
recipientId = RecipientId.UNKNOWN,
roomId = roomId,
credentials = CallLinkCredentials(
linkKeyBytes = callLinkRootKey.keyBytes,
adminPassBytes = callLinkUpdate.adminPassKey?.toByteArray()
),
state = SignalCallLinkState()
)
)
)
}
ApplicationDependencies.getJobManager().add(RefreshCallLinkDetailsJob(callLinkUpdate))
}

View File

@@ -137,7 +137,6 @@ class SignalCallLinkManager(
credentials: CallLinkCredentials
): Single<ReadCallLinkResult> {
return Single.create { emitter ->
callManager.readCallLink(
SignalStore.internalValues().groupCallingServer(),
requestCallLinkAuthCredentialPresentation(credentials.linkKeyBytes).serialize(),