fix: call messages expires with recipients expire settings

pull/2940/head
Audric Ackermann 5 months ago
parent 3a26285667
commit ccbe3e13b0

@ -1,3 +1,5 @@
import { isNil } from 'lodash';
/**
* This function is used to check that an optional property on a Protobuf object is not undefined or using a type-specific default value.
* https://protobuf.dev/programming-guides/proto/#optional
@ -10,7 +12,7 @@ function hasDefinedProperty<A extends object, B extends PropertyKey & keyof A>(
object: A,
property: B
) {
return Object.prototype.hasOwnProperty.call(object, property) !== false;
return !isNil(object) && Object.prototype.hasOwnProperty.call(object, property) !== false;
}
export const ProtobufUtils = {

@ -19,7 +19,7 @@ import { getConversationController } from '../session/conversations';
import { concatUInt8Array, getSodiumRenderer } from '../session/crypto';
import { removeMessagePadding } from '../session/crypto/BufferPadding';
import { DisappearingMessages } from '../session/disappearing_messages';
import { DisappearingMessageUpdate } from '../session/disappearing_messages/types';
import { ReadyToDisappearMsgUpdate } from '../session/disappearing_messages/types';
import { ProfileManager } from '../session/profile_manager/ProfileManager';
import { GroupUtils, UserUtils } from '../session/utils';
import { perfEnd, perfStart } from '../session/utils/Performance';
@ -547,10 +547,19 @@ export async function innerHandleSwarmContentMessage({
if (content.dataExtractionNotification) {
perfStart(`handleDataExtractionNotification-${envelope.id}`);
// DataExtractionNotification uses the expiration setting of our side of the 1o1 conversation. whatever we get in the contentMessage
const expirationTimer = senderConversationModel.getExpireTimer();
const expirationType = DisappearingMessages.changeToDisappearingMessageType(
senderConversationModel,
expirationTimer,
senderConversationModel.getExpirationMode()
);
await handleDataExtractionNotification(
envelope,
content.dataExtractionNotification as SignalService.DataExtractionNotification,
expireUpdate || null
{ expirationTimer, expirationType, messageExpirationFromRetrieve }
);
perfEnd(
`handleDataExtractionNotification-${envelope.id}`,
@ -838,7 +847,7 @@ async function handleMessageRequestResponse(
export async function handleDataExtractionNotification(
envelope: EnvelopePlus,
dataNotificationMessage: SignalService.DataExtractionNotification,
expireUpdate: DisappearingMessageUpdate | null
expireUpdate: ReadyToDisappearMsgUpdate
): Promise<void> {
// we currently don't care about the timestamp included in the field itself, just the timestamp of the envelope
const { type, timestamp: referencedAttachment } = dataNotificationMessage;
@ -871,6 +880,7 @@ export async function handleDataExtractionNotification(
source,
},
});
created = DisappearingMessages.getMessageReadyToDisappear(
convo,
created,

@ -21,6 +21,7 @@ import {
DisappearingMessageMode,
DisappearingMessageType,
DisappearingMessageUpdate,
ReadyToDisappearMsgUpdate,
} from './types';
async function destroyMessagesAndUpdateRedux(
@ -303,17 +304,15 @@ async function checkForExpireUpdateInContentMessage(
convoToUpdate: ConversationModel,
messageExpirationFromRetrieve: number | null
): Promise<DisappearingMessageUpdate | undefined> {
const dataMessage = content.dataMessage as SignalService.DataMessage;
const dataMessage = content.dataMessage as SignalService.DataMessage | undefined;
// We will only support legacy disappearing messages for a short period before disappearing messages v2 is unlocked
const isDisappearingMessagesV2Released = await ReleasedFeatures.checkIsDisappearMessageV2FeatureReleased();
const couldBeLegacyContentMessage = couldBeLegacyDisappearingMessageContent(content);
const isLegacyDataMessage = checkIsLegacyDisappearingDataMessage(
couldBeLegacyContentMessage,
dataMessage as SignalService.DataMessage
);
const isLegacyDataMessage =
dataMessage && checkIsLegacyDisappearingDataMessage(couldBeLegacyContentMessage, dataMessage);
const hasExpirationUpdateFlags =
dataMessage.flags === SignalService.DataMessage.Flags.EXPIRATION_TIMER_UPDATE;
dataMessage?.flags === SignalService.DataMessage.Flags.EXPIRATION_TIMER_UPDATE;
const isLegacyConversationSettingMessage = isDisappearingMessagesV2Released
? (isLegacyDataMessage || couldBeLegacyContentMessage) && hasExpirationUpdateFlags
@ -428,7 +427,7 @@ function getMessageReadyToDisappear(
conversationModel: ConversationModel,
messageModel: MessageModel,
messageFlags: number,
expireUpdate?: DisappearingMessageUpdate
expireUpdate?: ReadyToDisappearMsgUpdate
) {
if (conversationModel.isPublic()) {
throw Error(

@ -34,3 +34,8 @@ export type DisappearingMessageUpdate = {
isDisappearingMessagesV2Released?: boolean;
messageExpirationFromRetrieve: number | null;
};
export type ReadyToDisappearMsgUpdate = Pick<
DisappearingMessageUpdate,
'expirationType' | 'expirationTimer' | 'messageExpirationFromRetrieve'
>;

@ -1,10 +1,9 @@
import { ContentMessage } from '..';
import { SignalService } from '../../../../protobuf';
import { signalservice } from '../../../../protobuf/compiled';
import { TTL_DEFAULT } from '../../../constants';
import { MessageParams } from '../Message';
import { ExpirableMessage, ExpirableMessageParams } from '../ExpirableMessage';
interface CallMessageParams extends MessageParams {
interface CallMessageParams extends ExpirableMessageParams {
type: SignalService.CallMessage.Type;
sdpMLineIndexes?: Array<number>;
sdpMids?: Array<string>;
@ -12,7 +11,7 @@ interface CallMessageParams extends MessageParams {
uuid: string;
}
export class CallMessage extends ContentMessage {
export class CallMessage extends ExpirableMessage {
public readonly type: signalservice.CallMessage.Type;
public readonly sdpMLineIndexes?: Array<number>;
public readonly sdpMids?: Array<string>;

@ -2,7 +2,6 @@ import { getMessageQueue } from '../../..';
import { SignalService } from '../../../../protobuf';
import { SnodeNamespaces } from '../../../apis/snode_api/namespaces';
import { getConversationController } from '../../../conversations';
import { DisappearingMessages } from '../../../disappearing_messages';
import { PubKey } from '../../../types';
import { UserUtils } from '../../../utils';
import { ExpirableMessage, ExpirableMessageParams } from '../ExpirableMessage';
@ -55,18 +54,12 @@ export const sendDataExtractionNotification = async (
return;
}
const expireTimer = convo.getExpireTimer();
const expirationType = DisappearingMessages.changeToDisappearingMessageType(
convo,
expireTimer,
convo.getExpirationMode()
);
// DataExtractionNotification are expiring with the recipient, so don't include ours
const dataExtractionNotificationMessage = new DataExtractionNotificationMessage({
referencedAttachmentTimestamp,
timestamp: Date.now(),
expirationType,
expireTimer,
expirationType: null,
expireTimer: null,
});
const pubkey = PubKey.cast(conversationId);

@ -417,6 +417,8 @@ async function createOfferAndSendIt(recipient: string) {
type: SignalService.CallMessage.Type.OFFER,
sdps: [overridenSdps],
uuid: currentCallUUID,
expirationType: null, // Note: CallMessages are expiring based on the recipient's side expiration setting
expireTimer: null,
});
window.log.info(`sending '${offer.type}'' with callUUID: ${currentCallUUID}`);
@ -503,6 +505,8 @@ export async function USER_callRecipient(recipient: string) {
timestamp: now,
type: SignalService.CallMessage.Type.PRE_OFFER,
uuid: currentCallUUID,
expirationType: null, // Note: CallMessages are expiring based on the recipient's side expiration setting
expireTimer: null,
});
window.log.info('Sending preOffer message to ', ed25519Str(recipient));
@ -527,7 +531,7 @@ export async function USER_callRecipient(recipient: string) {
if (
expirationMode === 'legacy' ||
expirationMode === 'deleteAfterSend' ||
expirationMode === 'deleteAfterRead' // we are the one iniating the call, so that message is already read
expirationMode === 'deleteAfterRead' // we are the one initiaing the call, so that message is already read
) {
expirationStartTimestamp = DisappearingMessages.setExpirationStartTimestamp(
expirationMode,
@ -537,6 +541,7 @@ export async function USER_callRecipient(recipient: string) {
}
}
// Locally, that message must expire
await calledConvo?.addSingleOutgoingMessage({
callNotificationType: 'started-call',
sent_at: now,
@ -610,6 +615,8 @@ const iceSenderDebouncer = _.debounce(async (recipient: string) => {
sdpMids: validCandidates.map(c => c.sdpMid),
sdps: validCandidates.map(c => c.candidate),
uuid: currentCallUUID,
expirationType: null, // Note: CallMessages are expiring based on the recipient's side expiration setting
expireTimer: null,
});
window.log.info(
@ -957,6 +964,8 @@ export async function rejectCallAlreadyAnotherCall(fromSender: string, forcedUUI
type: SignalService.CallMessage.Type.END_CALL,
timestamp: Date.now(),
uuid: forcedUUID,
expirationType: null, // Note: CallMessages are expiring based on the recipient's side expiration setting
expireTimer: null,
});
await sendCallMessageAndSync(rejectCallMessage, fromSender);
@ -980,6 +989,8 @@ export async function USER_rejectIncomingCallRequest(fromSender: string) {
type: SignalService.CallMessage.Type.END_CALL,
timestamp: Date.now(),
uuid: aboutCallUUID,
expirationType: null, // Note: CallMessages are expiring based on the recipient's side expiration setting
expireTimer: null,
});
// sync the reject event so our other devices remove the popup too
await sendCallMessageAndSync(endCallMessage, fromSender);
@ -1022,6 +1033,8 @@ export async function USER_hangup(fromSender: string) {
type: SignalService.CallMessage.Type.END_CALL,
timestamp: Date.now(),
uuid: currentCallUUID,
expirationType: null, // Note: CallMessages are expiring based on the recipient's side expiration setting
expireTimer: null,
});
void getMessageQueue().sendToPubKeyNonDurably({
pubkey: PubKey.cast(fromSender),
@ -1098,6 +1111,8 @@ async function buildAnswerAndSendIt(sender: string) {
type: SignalService.CallMessage.Type.ANSWER,
sdps: [answerSdp],
uuid: currentCallUUID,
expirationType: null, // Note: CallMessages are expiring based on the recipient's side expiration setting
expireTimer: null,
});
window.log.info('sending ANSWER MESSAGE and sync');
@ -1272,6 +1287,8 @@ async function addMissedCallMessage(callerPubkey: string, sentAt: number) {
await incomingCallConversation.unhideIfNeeded(false);
}
// Note: Missed call messages are expiring with our side of the conversation settings.
const expirationMode = incomingCallConversation.getExpirationMode();
const expireTimer = incomingCallConversation.getExpireTimer() || 0;
let expirationType;

Loading…
Cancel
Save