From f3f9e41787358b8c3e10be4f206cc20654287701 Mon Sep 17 00:00:00 2001 From: Robert Long Date: Thu, 6 Jan 2022 15:24:59 -0800 Subject: [PATCH 1/4] Emit sent voip events --- src/webrtc/call.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/webrtc/call.ts b/src/webrtc/call.ts index d698a4e64..df92850da 100644 --- a/src/webrtc/call.ts +++ b/src/webrtc/call.ts @@ -134,6 +134,8 @@ export enum CallEvent { LengthChanged = 'length_changed', DataChannel = 'datachannel', + + SendVoipEvent = "send_voip_event", } export enum CallErrorCode { @@ -1995,6 +1997,13 @@ export class MatrixCall extends EventEmitter { }); if (this.opponentDeviceId) { + this.emit(CallEvent.SendVoipEvent, { + type: "toDevice", + eventType, + userId: this.invitee || this.getOpponentMember().userId, + content: { ...realContent, device_id: this.client.deviceId }, + }); + return this.client.sendToDevice(eventType, { [this.invitee || this.getOpponentMember().userId]: { [this.opponentDeviceId]: { @@ -2004,6 +2013,13 @@ export class MatrixCall extends EventEmitter { }, }); } else { + this.emit(CallEvent.SendVoipEvent, { + type: "sendEvent", + eventType, + roomId: this.roomId, + content: realContent, + }); + return this.client.sendEvent(this.roomId, eventType, realContent); } } From 18bb5c3079e42ad3594117fba8d12f146133df74 Mon Sep 17 00:00:00 2001 From: Robert Long Date: Thu, 6 Jan 2022 15:46:55 -0800 Subject: [PATCH 2/4] Log opponentDeviceId --- src/webrtc/call.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/webrtc/call.ts b/src/webrtc/call.ts index df92850da..1ce5d4e0b 100644 --- a/src/webrtc/call.ts +++ b/src/webrtc/call.ts @@ -2001,6 +2001,7 @@ export class MatrixCall extends EventEmitter { type: "toDevice", eventType, userId: this.invitee || this.getOpponentMember().userId, + opponentDeviceId: this.opponentDeviceId, content: { ...realContent, device_id: this.client.deviceId }, }); From 87bf1159673d36b810eb0090297b01239f53b4ca Mon Sep 17 00:00:00 2001 From: Robert Long Date: Mon, 10 Jan 2022 15:57:40 -0800 Subject: [PATCH 3/4] Use session ids to resolve refresh during invite/answer --- src/client.ts | 10 ++++++++++ src/webrtc/call.ts | 9 ++++++++- src/webrtc/callEventTypes.ts | 2 ++ src/webrtc/groupCall.ts | 20 +++++++++++++------- 4 files changed, 33 insertions(+), 8 deletions(-) diff --git a/src/client.ts b/src/client.ts index fd162128d..917b4215c 100644 --- a/src/client.ts +++ b/src/client.ts @@ -758,6 +758,7 @@ export class MatrixClient extends EventEmitter { protected exportedOlmDeviceToImport: IOlmDevice; protected txnCtr = 0; protected mediaHandler = new MediaHandler(this); + protected sessionId: string; constructor(opts: IMatrixClientCreateOpts) { super(); @@ -771,6 +772,7 @@ export class MatrixClient extends EventEmitter { this.usingExternalCrypto = opts.usingExternalCrypto; this.store = opts.store || new StubStore(); this.deviceId = opts.deviceId || null; + this.sessionId = randomString(10); const userId = opts.userId || null; this.credentials = { userId }; @@ -1259,6 +1261,14 @@ export class MatrixClient extends EventEmitter { return this.deviceId; } + /** + * Get the session ID of this client + * @return {string} session ID + */ + public getSessionId(): string { + return this.sessionId; + } + /** * Check if the runtime environment supports VoIP calling. * @return {boolean} True if VoIP is supported. diff --git a/src/webrtc/call.ts b/src/webrtc/call.ts index 1ce5d4e0b..e0b33da80 100644 --- a/src/webrtc/call.ts +++ b/src/webrtc/call.ts @@ -319,6 +319,7 @@ export class MatrixCall extends EventEmitter { private callLength = 0; private opponentDeviceId: string; + private opponentSessionId: string; public groupCallId: string; constructor(opts: CallOpts) { @@ -374,6 +375,10 @@ export class MatrixCall extends EventEmitter { return this.opponentMember; } + public getOpponentSessionId(): string { + return this.opponentSessionId; + } + public opponentCanBeTransferred(): boolean { return Boolean(this.opponentCaps && this.opponentCaps["m.call.transferee"]); } @@ -2002,7 +2007,7 @@ export class MatrixCall extends EventEmitter { eventType, userId: this.invitee || this.getOpponentMember().userId, opponentDeviceId: this.opponentDeviceId, - content: { ...realContent, device_id: this.client.deviceId }, + content: { ...realContent, device_id: this.client.deviceId, session_id: this.client.getSessionId() }, }); return this.client.sendToDevice(eventType, { @@ -2010,6 +2015,7 @@ export class MatrixCall extends EventEmitter { [this.opponentDeviceId]: { ...realContent, device_id: this.client.deviceId, + session_id: this.client.getSessionId(), }, }, }); @@ -2339,6 +2345,7 @@ export class MatrixCall extends EventEmitter { } this.opponentCaps = msg.capabilities || {} as CallCapabilities; this.opponentMember = this.client.getRoom(this.roomId).getMember(ev.getSender()); + this.opponentSessionId = msg.session_id; } private async addBufferedIceCandidates(): Promise { diff --git a/src/webrtc/callEventTypes.ts b/src/webrtc/callEventTypes.ts index c5b0063f9..28eeb6d94 100644 --- a/src/webrtc/callEventTypes.ts +++ b/src/webrtc/callEventTypes.ts @@ -36,6 +36,7 @@ export interface MCallBase { call_id: string; version: string | number; party_id?: string; + session_id?: string; } export interface MCallAnswer extends MCallBase { @@ -54,6 +55,7 @@ export interface MCallInviteNegotiate extends MCallBase { lifetime: number; capabilities?: CallCapabilities; invitee?: string; + session_id?: string; [SDPStreamMetadataKey]: SDPStreamMetadata; } diff --git a/src/webrtc/groupCall.ts b/src/webrtc/groupCall.ts index 3626e9693..8ca0ce767 100644 --- a/src/webrtc/groupCall.ts +++ b/src/webrtc/groupCall.ts @@ -73,6 +73,7 @@ export interface IGroupCallRoomMemberFeed { export interface IGroupCallRoomMemberDevice { "device_id": string; + "session_id": string; "feeds": IGroupCallRoomMemberFeed[]; } @@ -532,6 +533,7 @@ export class GroupCall extends EventEmitter { "m.devices": [ { "device_id": deviceId, + "session_id": this.client.getSessionId(), "feeds": this.getLocalFeeds().map((feed) => ({ purpose: feed.purpose, })), @@ -632,12 +634,6 @@ export class GroupCall extends EventEmitter { return; } - const existingCall = this.getCallByUserId(member.userId); - - if (existingCall) { - return; - } - const opponentDevice = this.getDeviceForMember(member.userId); if (!opponentDevice) { @@ -652,6 +648,12 @@ export class GroupCall extends EventEmitter { return; } + const existingCall = this.getCallByUserId(member.userId); + + if (existingCall && existingCall.getOpponentSessionId() === opponentDevice.session_id) { + return; + } + const newCall = createNewMatrixCall( this.client, this.room.roomId, @@ -668,7 +670,11 @@ export class GroupCall extends EventEmitter { newCall.createDataChannel("datachannel", this.dataChannelOptions); } - this.addCall(newCall); + if (existingCall) { + this.replaceCall(existingCall, newCall); + } else { + this.addCall(newCall); + } }; public getDeviceForMember(userId: string): IGroupCallRoomMemberDevice { From c91617a79925e67e6bcb3fa83119103c055df626 Mon Sep 17 00:00:00 2001 From: Robert Long Date: Mon, 10 Jan 2022 16:22:52 -0800 Subject: [PATCH 4/4] Force hangup replaced calls --- src/webrtc/groupCall.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/webrtc/groupCall.ts b/src/webrtc/groupCall.ts index 8ca0ce767..37efb2568 100644 --- a/src/webrtc/groupCall.ts +++ b/src/webrtc/groupCall.ts @@ -671,7 +671,7 @@ export class GroupCall extends EventEmitter { } if (existingCall) { - this.replaceCall(existingCall, newCall); + this.replaceCall(existingCall, newCall, true); } else { this.addCall(newCall); } @@ -734,7 +734,7 @@ export class GroupCall extends EventEmitter { this.emit(GroupCallEvent.CallsChanged, this.calls); } - private replaceCall(existingCall: MatrixCall, replacementCall: MatrixCall) { + private replaceCall(existingCall: MatrixCall, replacementCall: MatrixCall, forceHangup = false) { const existingCallIndex = this.calls.indexOf(existingCall); if (existingCallIndex === -1) { @@ -743,7 +743,7 @@ export class GroupCall extends EventEmitter { this.calls.splice(existingCallIndex, 1, replacementCall); - this.disposeCall(existingCall, CallErrorCode.Replaced); + this.disposeCall(existingCall, CallErrorCode.Replaced, forceHangup); this.initCall(replacementCall); this.emit(GroupCallEvent.CallsChanged, this.calls); @@ -793,7 +793,7 @@ export class GroupCall extends EventEmitter { onCallFeedsChanged(); } - private disposeCall(call: MatrixCall, hangupReason: CallErrorCode) { + private disposeCall(call: MatrixCall, hangupReason: CallErrorCode, forceHangup = false) { const opponentMemberId = getCallUserId(call); if (!opponentMemberId) { @@ -814,7 +814,7 @@ export class GroupCall extends EventEmitter { this.callHandlers.delete(opponentMemberId); - if (call.hangupReason === CallErrorCode.Replaced) { + if (call.hangupReason === CallErrorCode.Replaced && !forceHangup) { return; }