Integrate call links create/update/read apis.

This commit is contained in:
Alex Hart
2023-05-19 10:28:29 -03:00
committed by Nicholas Tinsley
parent 4d6d31d624
commit 5a38143987
60 changed files with 1986 additions and 191 deletions

View File

@@ -121,6 +121,7 @@ import org.thoughtcrime.securesms.recipients.RecipientId;
import org.thoughtcrime.securesms.recipients.RecipientUtil;
import org.thoughtcrime.securesms.ringrtc.RemotePeer;
import org.thoughtcrime.securesms.service.webrtc.WebRtcData;
import org.thoughtcrime.securesms.service.webrtc.links.CallLinkRoomId;
import org.thoughtcrime.securesms.sms.IncomingEncryptedMessage;
import org.thoughtcrime.securesms.sms.IncomingEndSessionMessage;
import org.thoughtcrime.securesms.sms.IncomingTextMessage;
@@ -133,8 +134,8 @@ import org.thoughtcrime.securesms.util.GroupUtil;
import org.thoughtcrime.securesms.util.IdentityUtil;
import org.thoughtcrime.securesms.util.LinkUtil;
import org.thoughtcrime.securesms.util.MediaUtil;
import org.thoughtcrime.securesms.util.MessageRecordUtil;
import org.thoughtcrime.securesms.util.MessageConstraintsUtil;
import org.thoughtcrime.securesms.util.MessageRecordUtil;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
@@ -1336,8 +1337,27 @@ public class MessageContentProcessor {
return;
}
GroupId groupId = GroupId.push(callEvent.getConversationId().toByteArray());
RecipientId recipientId = Recipient.externalGroupExact(groupId).getId();
RecipientId recipientId;
switch (type) {
case AD_HOC_CALL:
CallLinkRoomId callLinkRoomId = CallLinkRoomId.fromBytes(callEvent.getConversationId().toByteArray());
recipientId = SignalDatabase.recipients().getByCallLinkRoomId(callLinkRoomId).orElse(null);
break;
case GROUP_CALL:
GroupId groupId = GroupId.push(callEvent.getConversationId().toByteArray());
recipientId = Recipient.externalGroupExact(groupId).getId();
break;
default:
warn(envelopeTimestamp, "Group/Ad-hoc call event has a bad type " + type + ". Ignoring.");
return;
}
if (recipientId == null) {
Log.w(TAG, "Could not find a matching group or ad-hoc call. Dropping sync event.");
return;
}
CallTable.Call call = SignalDatabase.calls().getCallById(callId, recipientId);
if (call != null) {

View File

@@ -6,12 +6,17 @@ import com.mobilecoin.lib.exceptions.SerializationException
import org.signal.core.util.Hex
import org.signal.core.util.orNull
import org.signal.libsignal.protocol.util.Pair
import org.signal.ringrtc.CallException
import org.signal.ringrtc.CallLinkRootKey
import org.signal.ringrtc.CallLinkState
import org.thoughtcrime.securesms.attachments.Attachment
import org.thoughtcrime.securesms.attachments.DatabaseAttachment
import org.thoughtcrime.securesms.attachments.TombstoneAttachment
import org.thoughtcrime.securesms.components.emoji.EmojiUtil
import org.thoughtcrime.securesms.contactshare.Contact
import org.thoughtcrime.securesms.conversation.colors.AvatarColor
import org.thoughtcrime.securesms.crypto.SecurityEvent
import org.thoughtcrime.securesms.database.CallLinkTable
import org.thoughtcrime.securesms.database.CallTable
import org.thoughtcrime.securesms.database.GroupReceiptTable
import org.thoughtcrime.securesms.database.GroupTable
@@ -45,6 +50,7 @@ import org.thoughtcrime.securesms.jobs.MultiDeviceGroupUpdateJob
import org.thoughtcrime.securesms.jobs.MultiDeviceKeysUpdateJob
import org.thoughtcrime.securesms.jobs.MultiDeviceStickerPackSyncJob
import org.thoughtcrime.securesms.jobs.PushProcessEarlyMessagesJob
import org.thoughtcrime.securesms.jobs.RefreshCallLinkDetailsJob
import org.thoughtcrime.securesms.jobs.RefreshOwnProfileJob
import org.thoughtcrime.securesms.jobs.StickerPackDownloadJob
import org.thoughtcrime.securesms.keyvalue.SignalStore
@@ -79,6 +85,9 @@ import org.thoughtcrime.securesms.payments.MobileCoinPublicAddress
import org.thoughtcrime.securesms.ratelimit.RateLimitUtil
import org.thoughtcrime.securesms.recipients.Recipient
import org.thoughtcrime.securesms.recipients.RecipientId
import org.thoughtcrime.securesms.service.webrtc.links.CallLinkCredentials
import org.thoughtcrime.securesms.service.webrtc.links.CallLinkRoomId
import org.thoughtcrime.securesms.service.webrtc.links.SignalCallLinkState
import org.thoughtcrime.securesms.storage.StorageSyncHelper
import org.thoughtcrime.securesms.stories.Stories
import org.thoughtcrime.securesms.util.EarlyMessageCacheEntry
@@ -101,6 +110,7 @@ import org.whispersystems.signalservice.internal.push.SignalServiceProtos.Envelo
import org.whispersystems.signalservice.internal.push.SignalServiceProtos.StoryMessage
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.Configuration
import org.whispersystems.signalservice.internal.push.SignalServiceProtos.SyncMessage.FetchLatest
import org.whispersystems.signalservice.internal.push.SignalServiceProtos.SyncMessage.MessageRequestResponse
@@ -110,6 +120,7 @@ import org.whispersystems.signalservice.internal.push.SignalServiceProtos.SyncMe
import org.whispersystems.signalservice.internal.push.SignalServiceProtos.SyncMessage.StickerPackOperation
import org.whispersystems.signalservice.internal.push.SignalServiceProtos.SyncMessage.ViewOnceOpen
import java.io.IOException
import java.time.Instant
import java.util.Optional
import java.util.UUID
import kotlin.time.Duration.Companion.seconds
@@ -142,6 +153,7 @@ object SyncMessageProcessor {
syncMessage.hasKeys() && syncMessage.keys.hasStorageService() -> handleSynchronizeKeys(syncMessage.keys.storageService, envelope.timestamp)
syncMessage.hasContacts() -> handleSynchronizeContacts(syncMessage.contacts, envelope.timestamp)
syncMessage.hasCallEvent() -> handleSynchronizeCallEvent(syncMessage.callEvent, envelope.timestamp)
syncMessage.hasCallLinkUpdate() -> handleSynchronizeCallLink(syncMessage.callLinkUpdate, envelope.timestamp)
else -> warn(envelope.timestamp, "Contains no known sync types...")
}
}
@@ -1155,6 +1167,54 @@ object SyncMessageProcessor {
}
}
private fun handleSynchronizeCallLink(callLinkUpdate: CallLinkUpdate, envelopeTimestamp: Long) {
if (!callLinkUpdate.hasRootKey()) {
log(envelopeTimestamp, "Synchronize call link missing root key, ignoring.")
return
}
val callLinkRootKey = try {
CallLinkRootKey(callLinkUpdate.rootKey.toByteArray())
} catch (e: CallException) {
log(envelopeTimestamp, "Synchronize call link has invalid root key, ignoring.")
return
}
val roomId = CallLinkRoomId.fromCallLinkRootKey(callLinkRootKey)
if (SignalDatabase.callLinks.callLinkExists(roomId)) {
log(envelopeTimestamp, "Synchronize call link for a link we already know about. Updating credentials.")
SignalDatabase.callLinks.updateCallLinkCredentials(
roomId,
CallLinkCredentials(
callLinkUpdate.rootKey.toByteArray(),
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(
name = "",
restrictions = CallLinkState.Restrictions.UNKNOWN,
revoked = false,
expiration = Instant.MIN
),
avatarColor = AvatarColor.random()
)
)
ApplicationDependencies.getJobManager().add(RefreshCallLinkDetailsJob(callLinkUpdate))
}
private fun handleSynchronizeOneToOneCallEvent(callEvent: SyncMessage.CallEvent, envelopeTimestamp: Long) {
val callId: Long = callEvent.id
val timestamp: Long = callEvent.timestamp
@@ -1207,10 +1267,28 @@ object SyncMessageProcessor {
return
}
val groupId: GroupId = GroupId.push(callEvent.conversationId.toByteArray())
val recipientId = Recipient.externalGroupExact(groupId).id
val recipient: Recipient? = when (type) {
CallTable.Type.AD_HOC_CALL -> {
val callLinkRoomId = CallLinkRoomId.fromBytes(callEvent.conversationId.toByteArray())
val callLink = SignalDatabase.callLinks.getOrCreateCallLinkByRoomId(callLinkRoomId)
Recipient.resolved(callLink.recipientId)
}
CallTable.Type.GROUP_CALL -> {
val groupId: GroupId = GroupId.push(callEvent.conversationId.toByteArray())
Recipient.externalGroupExact(groupId)
}
else -> {
warn(envelopeTimestamp, "Unexpected type $type. Ignoring.")
null
}
}
val call = SignalDatabase.calls.getCallById(callId, recipientId)
if (recipient == null) {
warn(envelopeTimestamp, "Could not process conversation id.")
return
}
val call = SignalDatabase.calls.getCallById(callId, recipient.id)
if (call != null) {
if (call.type !== type) {
@@ -1221,7 +1299,7 @@ object SyncMessageProcessor {
CallTable.Event.DELETE -> SignalDatabase.calls.deleteGroupCall(call)
CallTable.Event.ACCEPTED -> {
if (call.timestamp < callEvent.timestamp) {
SignalDatabase.calls.setTimestamp(call.callId, recipientId, callEvent.timestamp)
SignalDatabase.calls.setTimestamp(call.callId, recipient.id, callEvent.timestamp)
}
if (callEvent.direction == SyncMessage.CallEvent.Direction.INCOMING) {
SignalDatabase.calls.acceptIncomingGroupCall(call)
@@ -1234,8 +1312,8 @@ object SyncMessageProcessor {
}
} else {
when (event) {
CallTable.Event.DELETE -> SignalDatabase.calls.insertDeletedGroupCallFromSyncEvent(callEvent.id, recipientId, direction, timestamp)
CallTable.Event.ACCEPTED -> SignalDatabase.calls.insertAcceptedGroupCall(callEvent.id, recipientId, direction, timestamp)
CallTable.Event.DELETE -> SignalDatabase.calls.insertDeletedGroupCallFromSyncEvent(callEvent.id, recipient.id, direction, timestamp)
CallTable.Event.ACCEPTED -> SignalDatabase.calls.insertAcceptedGroupCall(callEvent.id, recipient.id, direction, timestamp)
CallTable.Event.NOT_ACCEPTED -> warn("Unsupported event type " + event + ". Ignoring. timestamp: " + timestamp + " type: " + type + " direction: " + direction + " event: " + event + " hasPeer: " + callEvent.hasConversationId())
else -> warn("Unsupported event type " + event + ". Ignoring. timestamp: " + timestamp + " type: " + type + " direction: " + direction + " event: " + event + " hasPeer: " + callEvent.hasConversationId())
}