Call Disposition

This commit is contained in:
Jamie Kyle 2023-01-09 16:52:01 -08:00 committed by GitHub
parent 9927b132b9
commit e5638c0b20
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 445 additions and 53 deletions

View file

@ -37,7 +37,7 @@ import {
SignedPreKeys,
} from '../LibSignalStores';
import { verifySignature } from '../Curve';
import { strictAssert } from '../util/assert';
import { assertDev, strictAssert } from '../util/assert';
import type { BatcherType } from '../util/batcher';
import { createBatcher } from '../util/batcher';
import { drop } from '../util/drop';
@ -111,6 +111,7 @@ import {
GroupEvent,
GroupSyncEvent,
StoryRecipientUpdateEvent,
CallEventSyncEvent,
} from './messageReceiverEvents';
import * as log from '../logging/log';
import * as durations from '../util/durations';
@ -617,6 +618,11 @@ export default class MessageReceiver
handler: (ev: StoryRecipientUpdateEvent) => void
): void;
public override addEventListener(
name: 'callEventSync',
handler: (ev: CallEventSyncEvent) => void
): void;
public override addEventListener(name: string, handler: EventHandler): void {
return super.addEventListener(name, handler);
}
@ -2958,6 +2964,9 @@ export default class MessageReceiver
if (syncMessage.viewed && syncMessage.viewed.length) {
return this.handleViewed(envelope, syncMessage.viewed);
}
if (syncMessage.callEvent) {
return this.handleCallEvent(envelope, syncMessage.callEvent);
}
this.removeFromCache(envelope);
log.warn(
@ -3219,6 +3228,64 @@ export default class MessageReceiver
);
}
private async handleCallEvent(
envelope: ProcessedEnvelope,
callEvent: Proto.SyncMessage.ICallEvent
): Promise<void> {
const logId = getEnvelopeId(envelope);
log.info('MessageReceiver.handleCallEvent', logId);
const { peerUuid, callId } = callEvent;
if (!peerUuid) {
throw new Error('MessageReceiver.handleCallEvent: missing peerUuid');
}
if (!callId) {
throw new Error('MessageReceiver.handleCallEvent: missing callId');
}
logUnexpectedUrgentValue(envelope, 'callEventSync');
const peerUuidStr = bytesToUuid(peerUuid);
assertDev(
peerUuidStr != null,
'MessageReceiver.handleCallEvent: invalid peerUuid'
);
const { receivedAtCounter, timestamp } = envelope;
const wasIncoming =
callEvent.direction === Proto.SyncMessage.CallEvent.Direction.INCOMING;
const wasVideoCall =
callEvent.type === Proto.SyncMessage.CallEvent.Type.VIDEO_CALL;
const wasAccepted =
callEvent.event === Proto.SyncMessage.CallEvent.Event.ACCEPTED;
const wasDeclined =
callEvent.event === Proto.SyncMessage.CallEvent.Event.NOT_ACCEPTED;
const acceptedTime = wasAccepted ? timestamp : undefined;
const endedTime = wasDeclined ? timestamp : undefined;
const callEventSync = new CallEventSyncEvent(
{
timestamp: envelope.timestamp,
peerUuid: peerUuidStr,
callId: callId.toString(),
wasIncoming,
wasVideoCall,
wasDeclined,
acceptedTime,
endedTime,
receivedAtCounter,
},
this.removeFromCache.bind(this, envelope)
);
await this.dispatchAndWait(logId, callEventSync);
log.info('handleCallEvent: finished');
}
private async handleContacts(
envelope: ProcessedEnvelope,
contacts: Proto.SyncMessage.IContacts

View file

@ -1897,6 +1897,52 @@ export default class MessageSender {
};
}
static getCallEventSync(
peerUuid: string,
callId: string,
isVideoCall: boolean,
isIncoming: boolean,
isAccepted: boolean
): SingleProtoJobData {
const myUuid = window.textsecure.storage.user.getCheckedUuid();
const syncMessage = MessageSender.createSyncMessage();
const type = isVideoCall
? Proto.SyncMessage.CallEvent.Type.VIDEO_CALL
: Proto.SyncMessage.CallEvent.Type.AUDIO_CALL;
const direction = isIncoming
? Proto.SyncMessage.CallEvent.Direction.INCOMING
: Proto.SyncMessage.CallEvent.Direction.OUTGOING;
const event = isAccepted
? Proto.SyncMessage.CallEvent.Event.ACCEPTED
: Proto.SyncMessage.CallEvent.Event.NOT_ACCEPTED;
syncMessage.callEvent = new Proto.SyncMessage.CallEvent({
peerUuid: uuidToBytes(peerUuid),
callId: Long.fromString(callId),
type,
direction,
event,
timestamp: Long.fromNumber(Date.now()),
});
const contentMessage = new Proto.Content();
contentMessage.syncMessage = syncMessage;
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
return {
contentHint: ContentHint.RESENDABLE,
identifier: myUuid.toString(),
isSyncMessage: true,
protoBase64: Bytes.toBase64(
Proto.Content.encode(contentMessage).finish()
),
type: 'callEventSync',
urgent: false,
};
}
static getVerificationSync(
destinationE164: string | undefined,
destinationUuid: string | undefined,

View file

@ -404,6 +404,27 @@ export class ViewSyncEvent extends ConfirmableEvent {
}
}
export type CallEventSyncEventData = Readonly<{
timestamp: number;
peerUuid: string;
callId: string;
wasVideoCall: boolean;
wasIncoming: boolean;
wasDeclined: boolean;
acceptedTime: number | undefined;
endedTime: number | undefined;
receivedAtCounter: number;
}>;
export class CallEventSyncEvent extends ConfirmableEvent {
constructor(
public readonly callEvent: CallEventSyncEventData,
confirm: ConfirmCallback
) {
super('callEventSync', confirm);
}
}
export type StoryRecipientUpdateData = Readonly<{
destinationUuid: string;
storyMessageRecipients: Array<Proto.SyncMessage.Sent.IStoryMessageRecipient>;