Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Fix calls on homeservers without the unstable thirdparty endpoints #8931

Merged
merged 3 commits into from
Jul 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 33 additions & 18 deletions src/CallHandler.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -265,28 +265,43 @@ export default class CallHandler extends EventEmitter {
return this.supportsSipNativeVirtual;
}

public pstnLookup(phoneNumber: string): Promise<ThirdpartyLookupResponse[]> {
return MatrixClientPeg.get().getThirdpartyUser(
this.pstnSupportPrefixed ? PROTOCOL_PSTN_PREFIXED : PROTOCOL_PSTN, {
'm.id.phone': phoneNumber,
},
);
public async pstnLookup(phoneNumber: string): Promise<ThirdpartyLookupResponse[]> {
try {
return await MatrixClientPeg.get().getThirdpartyUser(
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[]> {
return MatrixClientPeg.get().getThirdpartyUser(
PROTOCOL_SIP_VIRTUAL, {
'native_mxid': nativeMxid,
},
);
public async sipVirtualLookup(nativeMxid: string): Promise<ThirdpartyLookupResponse[]> {
try {
return await MatrixClientPeg.get().getThirdpartyUser(
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[]> {
return MatrixClientPeg.get().getThirdpartyUser(
PROTOCOL_SIP_NATIVE, {
'virtual_mxid': virtualMxid,
},
);
public async sipNativeLookup(virtualMxid: string): Promise<ThirdpartyLookupResponse[]> {
try {
return await MatrixClientPeg.get().getThirdpartyUser(
PROTOCOL_SIP_NATIVE, {
'virtual_mxid': virtualMxid,
},
);
} catch (e) {
logger.warn('Failed to query identity for SIP user', e);
return Promise.resolve([]);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we log the errors at least?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I log some very basic message now, but not sure what to properly put there :3

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should probably be a warning or error rather than just log

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, it isn't really an error in most cases though. If a homeserver doesn't support that protocol, then it won't be hosting a bridge like that either and those endpoints don't work over federation anyway. I can make it a warning but for most people that is may be nice to know, but it clearly isn't an error, since they are not running a SIP bridge.

}
}

private onCallIncoming = (call: MatrixCall): void => {
Expand Down
95 changes: 90 additions & 5 deletions test/CallHandler-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ class FakeCall extends EventEmitter {
roomId: string;
callId = "fake call id";

constructor(roomId) {
constructor(roomId: string) {
super();

this.roomId = roomId;
Expand All @@ -104,14 +104,14 @@ function untilCallHandlerEvent(callHandler: CallHandler, event: CallHandlerEvent
describe('CallHandler', () => {
let dmRoomMap;
let callHandler;
let audioElement;
let audioElement: HTMLAudioElement;
let fakeCall;

// what addresses the app has looked up via pstn and native lookup
let pstnLookup: string;
let nativeLookup: string;

beforeEach(() => {
beforeEach(async () => {
stubClient();
MatrixClientPeg.get().createCall = roomId => {
if (fakeCall && fakeCall.roomId !== roomId) {
Expand Down Expand Up @@ -151,7 +151,7 @@ describe('CallHandler', () => {
};

dmRoomMap = {
getUserIdForRoomId: roomId => {
getUserIdForRoomId: (roomId: string) => {
if (roomId === NATIVE_ROOM_ALICE) {
return NATIVE_ALICE;
} else if (roomId === NATIVE_ROOM_BOB) {
Expand All @@ -164,7 +164,7 @@ describe('CallHandler', () => {
return null;
}
},
getDMRoomsForUserId: userId => {
getDMRoomsForUserId: (userId: string) => {
if (userId === NATIVE_ALICE) {
return [NATIVE_ROOM_ALICE];
} else if (userId === NATIVE_BOB) {
Expand Down Expand Up @@ -322,3 +322,88 @@ describe('CallHandler', () => {
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);
});
});