Fix calls on homeservers without the unstable thirdparty endpoints (#8931)

* Fix calls on homeservers without the unstable thirdparty endpoints

Calling that endpoint throws an error and aborts the entire call. We do
check if an empty list or null is returned by that endpoint everywhere,
so returning an empty list simulates the thirdparty stuff just not being
found.

Checking for "this.supportsSipNativeVirtual" doesn't necessarily work,
since that might not be set yet and as such breaks calls that rely on
this functionality working.

fixes https://github.com/vector-im/element-web/issues/21680

Signed-off-by: Nicolas Werner <nicolas.werner@hotmail.de>

* Address review comments

* Make log message a warning

Signed-off-by: Nicolas Werner <nicolas.werner@hotmail.de>
pull/28217/head
DeepBlueV7.X 2022-07-01 12:43:42 +00:00 committed by GitHub
parent 1ef11a162c
commit d8d4ade1b7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 123 additions and 23 deletions

View File

@ -265,28 +265,43 @@ export default class CallHandler extends EventEmitter {
return this.supportsSipNativeVirtual; return this.supportsSipNativeVirtual;
} }
public pstnLookup(phoneNumber: string): Promise<ThirdpartyLookupResponse[]> { public async pstnLookup(phoneNumber: string): Promise<ThirdpartyLookupResponse[]> {
return MatrixClientPeg.get().getThirdpartyUser( try {
this.pstnSupportPrefixed ? PROTOCOL_PSTN_PREFIXED : PROTOCOL_PSTN, { return await MatrixClientPeg.get().getThirdpartyUser(
'm.id.phone': phoneNumber, this.pstnSupportPrefixed ? PROTOCOL_PSTN_PREFIXED : PROTOCOL_PSTN, {
}, 'm.id.phone': phoneNumber,
); },
);
} catch (e) {
logger.warn('Failed to lookup user from phone number', e);
return Promise.resolve([]);
}
} }
public sipVirtualLookup(nativeMxid: string): Promise<ThirdpartyLookupResponse[]> { public async sipVirtualLookup(nativeMxid: string): Promise<ThirdpartyLookupResponse[]> {
return MatrixClientPeg.get().getThirdpartyUser( try {
PROTOCOL_SIP_VIRTUAL, { return await MatrixClientPeg.get().getThirdpartyUser(
'native_mxid': nativeMxid, PROTOCOL_SIP_VIRTUAL, {
}, 'native_mxid': nativeMxid,
); },
);
} catch (e) {
logger.warn('Failed to query SIP identity for user', e);
return Promise.resolve([]);
}
} }
public sipNativeLookup(virtualMxid: string): Promise<ThirdpartyLookupResponse[]> { public async sipNativeLookup(virtualMxid: string): Promise<ThirdpartyLookupResponse[]> {
return MatrixClientPeg.get().getThirdpartyUser( try {
PROTOCOL_SIP_NATIVE, { return await MatrixClientPeg.get().getThirdpartyUser(
'virtual_mxid': virtualMxid, PROTOCOL_SIP_NATIVE, {
}, 'virtual_mxid': virtualMxid,
); },
);
} catch (e) {
logger.warn('Failed to query identity for SIP user', e);
return Promise.resolve([]);
}
} }
private onCallIncoming = (call: MatrixCall): void => { private onCallIncoming = (call: MatrixCall): void => {

View File

@ -79,7 +79,7 @@ class FakeCall extends EventEmitter {
roomId: string; roomId: string;
callId = "fake call id"; callId = "fake call id";
constructor(roomId) { constructor(roomId: string) {
super(); super();
this.roomId = roomId; this.roomId = roomId;
@ -104,14 +104,14 @@ function untilCallHandlerEvent(callHandler: CallHandler, event: CallHandlerEvent
describe('CallHandler', () => { describe('CallHandler', () => {
let dmRoomMap; let dmRoomMap;
let callHandler; let callHandler;
let audioElement; let audioElement: HTMLAudioElement;
let fakeCall; let fakeCall;
// what addresses the app has looked up via pstn and native lookup // what addresses the app has looked up via pstn and native lookup
let pstnLookup: string; let pstnLookup: string;
let nativeLookup: string; let nativeLookup: string;
beforeEach(() => { beforeEach(async () => {
stubClient(); stubClient();
MatrixClientPeg.get().createCall = roomId => { MatrixClientPeg.get().createCall = roomId => {
if (fakeCall && fakeCall.roomId !== roomId) { if (fakeCall && fakeCall.roomId !== roomId) {
@ -151,7 +151,7 @@ describe('CallHandler', () => {
}; };
dmRoomMap = { dmRoomMap = {
getUserIdForRoomId: roomId => { getUserIdForRoomId: (roomId: string) => {
if (roomId === NATIVE_ROOM_ALICE) { if (roomId === NATIVE_ROOM_ALICE) {
return NATIVE_ALICE; return NATIVE_ALICE;
} else if (roomId === NATIVE_ROOM_BOB) { } else if (roomId === NATIVE_ROOM_BOB) {
@ -164,7 +164,7 @@ describe('CallHandler', () => {
return null; return null;
} }
}, },
getDMRoomsForUserId: userId => { getDMRoomsForUserId: (userId: string) => {
if (userId === NATIVE_ALICE) { if (userId === NATIVE_ALICE) {
return [NATIVE_ROOM_ALICE]; return [NATIVE_ROOM_ALICE];
} else if (userId === NATIVE_BOB) { } else if (userId === NATIVE_BOB) {
@ -322,3 +322,88 @@ describe('CallHandler', () => {
expect(callHandler.getCallForRoom(NATIVE_ROOM_CHARLIE)).toBe(fakeCall); expect(callHandler.getCallForRoom(NATIVE_ROOM_CHARLIE)).toBe(fakeCall);
}); });
}); });
describe('CallHandler without third party protocols', () => {
let dmRoomMap;
let callHandler: CallHandler;
let audioElement: HTMLAudioElement;
let fakeCall;
beforeEach(() => {
stubClient();
MatrixClientPeg.get().createCall = roomId => {
if (fakeCall && fakeCall.roomId !== roomId) {
throw new Error("Only one call is supported!");
}
fakeCall = new FakeCall(roomId);
return fakeCall;
};
MatrixClientPeg.get().getThirdpartyProtocols = () => {
throw new Error("Endpoint unsupported.");
};
callHandler = new CallHandler();
callHandler.start();
const nativeRoomAlice = mkStubDM(NATIVE_ROOM_ALICE, NATIVE_ALICE);
MatrixClientPeg.get().getRoom = roomId => {
switch (roomId) {
case NATIVE_ROOM_ALICE:
return nativeRoomAlice;
}
};
dmRoomMap = {
getUserIdForRoomId: (roomId: string) => {
if (roomId === NATIVE_ROOM_ALICE) {
return NATIVE_ALICE;
} else {
return null;
}
},
getDMRoomsForUserId: (userId: string) => {
if (userId === NATIVE_ALICE) {
return [NATIVE_ROOM_ALICE];
} else {
return [];
}
},
};
DMRoomMap.setShared(dmRoomMap);
MatrixClientPeg.get().getThirdpartyUser = (_proto, _params) => {
throw new Error("Endpoint unsupported.");
};
audioElement = document.createElement('audio');
audioElement.id = "remoteAudio";
document.body.appendChild(audioElement);
});
afterEach(() => {
callHandler.stop();
DMRoomMap.setShared(null);
// @ts-ignore
window.mxCallHandler = null;
fakeCall = null;
MatrixClientPeg.unset();
document.body.removeChild(audioElement);
SdkConfig.unset();
});
it('should still start a native call', async () => {
callHandler.placeCall(NATIVE_ROOM_ALICE, CallType.Voice);
await untilCallHandlerEvent(callHandler, CallHandlerEvent.CallState);
// Check that a call was started: its room on the protocol level
// should be the virtual room
expect(fakeCall.roomId).toEqual(NATIVE_ROOM_ALICE);
// but it should appear to the user to be in thw native room for Bob
expect(callHandler.roomIdForCall(fakeCall)).toEqual(NATIVE_ROOM_ALICE);
});
});