You've already forked matrix-js-sdk
mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-08-07 23:02:56 +03:00
Don't attempt to adjust for clock skews when calculating group call membership expiry (#4340)
* Use origin server timestamp for calculating group call membership expiry * Fix tests * Docs * Refactor comments to reflect that the logic hasn't changed * Make comment maintainable * Fix up merge * Fix test
This commit is contained in:
@@ -98,20 +98,6 @@ describe("CallMembership", () => {
|
|||||||
expect(membership.getAbsoluteExpiry()).toEqual(5000 + 1000);
|
expect(membership.getAbsoluteExpiry()).toEqual(5000 + 1000);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("considers memberships unexpired if local age low enough", () => {
|
|
||||||
const fakeEvent = makeMockEvent(1000);
|
|
||||||
fakeEvent.getLocalAge = jest.fn().mockReturnValue(3000);
|
|
||||||
const membership = new CallMembership(fakeEvent, membershipTemplate);
|
|
||||||
expect(membership.isExpired()).toEqual(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("considers memberships expired when local age large", () => {
|
|
||||||
const fakeEvent = makeMockEvent(1000);
|
|
||||||
fakeEvent.localTimestamp = Date.now() - 6000;
|
|
||||||
const membership = new CallMembership(fakeEvent, membershipTemplate);
|
|
||||||
expect(membership.isExpired()).toEqual(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("returns preferred foci", () => {
|
it("returns preferred foci", () => {
|
||||||
const fakeEvent = makeMockEvent();
|
const fakeEvent = makeMockEvent();
|
||||||
const mockFocus = { type: "this_is_a_mock_focus" };
|
const mockFocus = { type: "this_is_a_mock_focus" };
|
||||||
@@ -198,13 +184,6 @@ describe("CallMembership", () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
// server origin timestamp for this event is 1000
|
// server origin timestamp for this event is 1000
|
||||||
fakeEvent = makeMockEvent(1000);
|
fakeEvent = makeMockEvent(1000);
|
||||||
// our clock would have been at 2000 at the creation time (our clock at event receive time - age)
|
|
||||||
// (ie. the local clock is 1 second ahead of the servers' clocks)
|
|
||||||
fakeEvent.localTimestamp = 2000;
|
|
||||||
|
|
||||||
// for simplicity's sake, we say that the event's age is zero
|
|
||||||
fakeEvent.getLocalAge = jest.fn().mockReturnValue(0);
|
|
||||||
|
|
||||||
membership = new CallMembership(fakeEvent!, membershipTemplate);
|
membership = new CallMembership(fakeEvent!, membershipTemplate);
|
||||||
|
|
||||||
jest.useFakeTimers();
|
jest.useFakeTimers();
|
||||||
@@ -215,6 +194,13 @@ describe("CallMembership", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("converts expiry time into local clock", () => {
|
it("converts expiry time into local clock", () => {
|
||||||
|
// our clock would have been at 2000 at the creation time (our clock at event receive time - age)
|
||||||
|
// (ie. the local clock is 1 second ahead of the servers' clocks)
|
||||||
|
fakeEvent.localTimestamp = 2000;
|
||||||
|
|
||||||
|
// for simplicity's sake, we say that the event's age is zero
|
||||||
|
fakeEvent.getLocalAge = jest.fn().mockReturnValue(0);
|
||||||
|
|
||||||
// for sanity's sake, make sure the server-relative expiry time is what we expect
|
// for sanity's sake, make sure the server-relative expiry time is what we expect
|
||||||
expect(membership.getAbsoluteExpiry()).toEqual(6000);
|
expect(membership.getAbsoluteExpiry()).toEqual(6000);
|
||||||
// therefore the expiry time converted to our clock should be 1 second later
|
// therefore the expiry time converted to our clock should be 1 second later
|
||||||
@@ -223,7 +209,8 @@ describe("CallMembership", () => {
|
|||||||
|
|
||||||
it("calculates time until expiry", () => {
|
it("calculates time until expiry", () => {
|
||||||
jest.setSystemTime(2000);
|
jest.setSystemTime(2000);
|
||||||
expect(membership.getMsUntilExpiry()).toEqual(5000);
|
// should be using absolute expiry time
|
||||||
|
expect(membership.getMsUntilExpiry()).toEqual(4000);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -73,14 +73,17 @@ describe("MatrixRTCSession", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("ignores expired memberships events", () => {
|
it("ignores expired memberships events", () => {
|
||||||
|
jest.useFakeTimers();
|
||||||
const expiredMembership = Object.assign({}, membershipTemplate);
|
const expiredMembership = Object.assign({}, membershipTemplate);
|
||||||
expiredMembership.expires = 1000;
|
expiredMembership.expires = 1000;
|
||||||
expiredMembership.device_id = "EXPIRED";
|
expiredMembership.device_id = "EXPIRED";
|
||||||
const mockRoom = makeMockRoom([membershipTemplate, expiredMembership], 10000);
|
const mockRoom = makeMockRoom([membershipTemplate, expiredMembership]);
|
||||||
|
|
||||||
|
jest.advanceTimersByTime(2000);
|
||||||
sess = MatrixRTCSession.roomSessionForRoom(client, mockRoom);
|
sess = MatrixRTCSession.roomSessionForRoom(client, mockRoom);
|
||||||
expect(sess?.memberships.length).toEqual(1);
|
expect(sess?.memberships.length).toEqual(1);
|
||||||
expect(sess?.memberships[0].deviceId).toEqual("AAAAAAA");
|
expect(sess?.memberships[0].deviceId).toEqual("AAAAAAA");
|
||||||
|
jest.useRealTimers();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("ignores memberships events of members not in the room", () => {
|
it("ignores memberships events of members not in the room", () => {
|
||||||
@@ -91,12 +94,15 @@ describe("MatrixRTCSession", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("honours created_ts", () => {
|
it("honours created_ts", () => {
|
||||||
|
jest.useFakeTimers();
|
||||||
|
jest.setSystemTime(500);
|
||||||
const expiredMembership = Object.assign({}, membershipTemplate);
|
const expiredMembership = Object.assign({}, membershipTemplate);
|
||||||
expiredMembership.created_ts = 500;
|
expiredMembership.created_ts = 500;
|
||||||
expiredMembership.expires = 1000;
|
expiredMembership.expires = 1000;
|
||||||
const mockRoom = makeMockRoom([expiredMembership]);
|
const mockRoom = makeMockRoom([expiredMembership]);
|
||||||
sess = MatrixRTCSession.roomSessionForRoom(client, mockRoom);
|
sess = MatrixRTCSession.roomSessionForRoom(client, mockRoom);
|
||||||
expect(sess?.memberships[0].getAbsoluteExpiry()).toEqual(1500);
|
expect(sess?.memberships[0].getAbsoluteExpiry()).toEqual(1500);
|
||||||
|
jest.useRealTimers();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("returns empty session if no membership events are present", () => {
|
it("returns empty session if no membership events are present", () => {
|
||||||
@@ -304,6 +310,8 @@ describe("MatrixRTCSession", () => {
|
|||||||
|
|
||||||
describe("getOldestMembership", () => {
|
describe("getOldestMembership", () => {
|
||||||
it("returns the oldest membership event", () => {
|
it("returns the oldest membership event", () => {
|
||||||
|
jest.useFakeTimers();
|
||||||
|
jest.setSystemTime(4000);
|
||||||
const mockRoom = makeMockRoom([
|
const mockRoom = makeMockRoom([
|
||||||
Object.assign({}, membershipTemplate, { device_id: "foo", created_ts: 3000 }),
|
Object.assign({}, membershipTemplate, { device_id: "foo", created_ts: 3000 }),
|
||||||
Object.assign({}, membershipTemplate, { device_id: "old", created_ts: 1000 }),
|
Object.assign({}, membershipTemplate, { device_id: "old", created_ts: 1000 }),
|
||||||
@@ -312,12 +320,15 @@ describe("MatrixRTCSession", () => {
|
|||||||
|
|
||||||
sess = MatrixRTCSession.roomSessionForRoom(client, mockRoom);
|
sess = MatrixRTCSession.roomSessionForRoom(client, mockRoom);
|
||||||
expect(sess.getOldestMembership()!.deviceId).toEqual("old");
|
expect(sess.getOldestMembership()!.deviceId).toEqual("old");
|
||||||
|
jest.useRealTimers();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("getsActiveFocus", () => {
|
describe("getsActiveFocus", () => {
|
||||||
const activeFociConfig = { type: "livekit", livekit_service_url: "https://active.url" };
|
const activeFociConfig = { type: "livekit", livekit_service_url: "https://active.url" };
|
||||||
it("gets the correct active focus with oldest_membership", () => {
|
it("gets the correct active focus with oldest_membership", () => {
|
||||||
|
jest.useFakeTimers();
|
||||||
|
jest.setSystemTime(3000);
|
||||||
const mockRoom = makeMockRoom([
|
const mockRoom = makeMockRoom([
|
||||||
Object.assign({}, membershipTemplate, {
|
Object.assign({}, membershipTemplate, {
|
||||||
device_id: "foo",
|
device_id: "foo",
|
||||||
@@ -335,6 +346,7 @@ describe("MatrixRTCSession", () => {
|
|||||||
focus_selection: "oldest_membership",
|
focus_selection: "oldest_membership",
|
||||||
});
|
});
|
||||||
expect(sess.getActiveFocus()).toBe(activeFociConfig);
|
expect(sess.getActiveFocus()).toBe(activeFociConfig);
|
||||||
|
jest.useRealTimers();
|
||||||
});
|
});
|
||||||
it("does not provide focus if the selction method is unknown", () => {
|
it("does not provide focus if the selction method is unknown", () => {
|
||||||
const mockRoom = makeMockRoom([
|
const mockRoom = makeMockRoom([
|
||||||
@@ -356,6 +368,8 @@ describe("MatrixRTCSession", () => {
|
|||||||
expect(sess.getActiveFocus()).toBe(undefined);
|
expect(sess.getActiveFocus()).toBe(undefined);
|
||||||
});
|
});
|
||||||
it("gets the correct active focus legacy", () => {
|
it("gets the correct active focus legacy", () => {
|
||||||
|
jest.useFakeTimers();
|
||||||
|
jest.setSystemTime(3000);
|
||||||
const mockRoom = makeMockRoom([
|
const mockRoom = makeMockRoom([
|
||||||
Object.assign({}, membershipTemplate, {
|
Object.assign({}, membershipTemplate, {
|
||||||
device_id: "foo",
|
device_id: "foo",
|
||||||
@@ -370,6 +384,7 @@ describe("MatrixRTCSession", () => {
|
|||||||
|
|
||||||
sess.joinRoomSession([{ type: "livekit", livekit_service_url: "htts://test.org" }]);
|
sess.joinRoomSession([{ type: "livekit", livekit_service_url: "htts://test.org" }]);
|
||||||
expect(sess.getActiveFocus()).toBe(activeFociConfig);
|
expect(sess.getActiveFocus()).toBe(activeFociConfig);
|
||||||
|
jest.useRealTimers();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -513,9 +528,8 @@ describe("MatrixRTCSession", () => {
|
|||||||
|
|
||||||
const eventContent = await eventSentPromise;
|
const eventContent = await eventSentPromise;
|
||||||
|
|
||||||
// definitely should have renewed by 1 second before the expiry!
|
jest.setSystemTime(1000);
|
||||||
const timeElapsed = 60 * 60 * 1000 - 1000;
|
const event = mockRTCEvent(eventContent.memberships, mockRoom.roomId);
|
||||||
const event = mockRTCEvent(eventContent.memberships, mockRoom.roomId, timeElapsed);
|
|
||||||
const getState = mockRoom.getLiveTimeline().getState(EventTimeline.FORWARDS)!;
|
const getState = mockRoom.getLiveTimeline().getState(EventTimeline.FORWARDS)!;
|
||||||
getState.getStateEvents = jest.fn().mockReturnValue(event);
|
getState.getStateEvents = jest.fn().mockReturnValue(event);
|
||||||
getState.events = new Map([
|
getState.events = new Map([
|
||||||
@@ -538,6 +552,8 @@ describe("MatrixRTCSession", () => {
|
|||||||
|
|
||||||
sendStateEventMock.mockReset().mockImplementation(resolveFn);
|
sendStateEventMock.mockReset().mockImplementation(resolveFn);
|
||||||
|
|
||||||
|
// definitely should have renewed by 1 second before the expiry!
|
||||||
|
const timeElapsed = 60 * 60 * 1000 - 1000;
|
||||||
jest.setSystemTime(Date.now() + timeElapsed);
|
jest.setSystemTime(Date.now() + timeElapsed);
|
||||||
jest.advanceTimersByTime(timeElapsed);
|
jest.advanceTimersByTime(timeElapsed);
|
||||||
await eventReSentPromise;
|
await eventReSentPromise;
|
||||||
@@ -685,7 +701,7 @@ describe("MatrixRTCSession", () => {
|
|||||||
|
|
||||||
mockRoom.getLiveTimeline().getState = jest
|
mockRoom.getLiveTimeline().getState = jest
|
||||||
.fn()
|
.fn()
|
||||||
.mockReturnValue(makeMockRoomState([membershipTemplate, member2], mockRoom.roomId, undefined));
|
.mockReturnValue(makeMockRoomState([membershipTemplate, member2], mockRoom.roomId));
|
||||||
sess.onMembershipUpdate();
|
sess.onMembershipUpdate();
|
||||||
|
|
||||||
await keysSentPromise2;
|
await keysSentPromise2;
|
||||||
@@ -711,7 +727,7 @@ describe("MatrixRTCSession", () => {
|
|||||||
const mockRoom = makeMockRoom([member1, member2]);
|
const mockRoom = makeMockRoom([member1, member2]);
|
||||||
mockRoom.getLiveTimeline().getState = jest
|
mockRoom.getLiveTimeline().getState = jest
|
||||||
.fn()
|
.fn()
|
||||||
.mockReturnValue(makeMockRoomState([member1, member2], mockRoom.roomId, undefined));
|
.mockReturnValue(makeMockRoomState([member1, member2], mockRoom.roomId));
|
||||||
|
|
||||||
sess = MatrixRTCSession.roomSessionForRoom(client, mockRoom);
|
sess = MatrixRTCSession.roomSessionForRoom(client, mockRoom);
|
||||||
sess.joinRoomSession([mockFocus], mockFocus, { manageMediaKeys: true });
|
sess.joinRoomSession([mockFocus], mockFocus, { manageMediaKeys: true });
|
||||||
@@ -760,7 +776,7 @@ describe("MatrixRTCSession", () => {
|
|||||||
const mockRoom = makeMockRoom([member1, member2]);
|
const mockRoom = makeMockRoom([member1, member2]);
|
||||||
mockRoom.getLiveTimeline().getState = jest
|
mockRoom.getLiveTimeline().getState = jest
|
||||||
.fn()
|
.fn()
|
||||||
.mockReturnValue(makeMockRoomState([member1, member2], mockRoom.roomId, undefined));
|
.mockReturnValue(makeMockRoomState([member1, member2], mockRoom.roomId));
|
||||||
|
|
||||||
sess = MatrixRTCSession.roomSessionForRoom(client, mockRoom);
|
sess = MatrixRTCSession.roomSessionForRoom(client, mockRoom);
|
||||||
sess.joinRoomSession([mockFocus], mockFocus, { manageMediaKeys: true });
|
sess.joinRoomSession([mockFocus], mockFocus, { manageMediaKeys: true });
|
||||||
@@ -825,6 +841,7 @@ describe("MatrixRTCSession", () => {
|
|||||||
|
|
||||||
it("Re-sends key if a member changes created_ts", async () => {
|
it("Re-sends key if a member changes created_ts", async () => {
|
||||||
jest.useFakeTimers();
|
jest.useFakeTimers();
|
||||||
|
jest.setSystemTime(1000);
|
||||||
try {
|
try {
|
||||||
const keysSentPromise1 = new Promise((resolve) => {
|
const keysSentPromise1 = new Promise((resolve) => {
|
||||||
sendEventMock.mockImplementation(resolve);
|
sendEventMock.mockImplementation(resolve);
|
||||||
@@ -840,7 +857,7 @@ describe("MatrixRTCSession", () => {
|
|||||||
const mockRoom = makeMockRoom([member1, member2]);
|
const mockRoom = makeMockRoom([member1, member2]);
|
||||||
mockRoom.getLiveTimeline().getState = jest
|
mockRoom.getLiveTimeline().getState = jest
|
||||||
.fn()
|
.fn()
|
||||||
.mockReturnValue(makeMockRoomState([member1, member2], mockRoom.roomId, undefined));
|
.mockReturnValue(makeMockRoomState([member1, member2], mockRoom.roomId));
|
||||||
|
|
||||||
sess = MatrixRTCSession.roomSessionForRoom(client, mockRoom);
|
sess = MatrixRTCSession.roomSessionForRoom(client, mockRoom);
|
||||||
sess.joinRoomSession([mockFocus], mockFocus, { manageMediaKeys: true });
|
sess.joinRoomSession([mockFocus], mockFocus, { manageMediaKeys: true });
|
||||||
@@ -938,7 +955,7 @@ describe("MatrixRTCSession", () => {
|
|||||||
|
|
||||||
mockRoom.getLiveTimeline().getState = jest
|
mockRoom.getLiveTimeline().getState = jest
|
||||||
.fn()
|
.fn()
|
||||||
.mockReturnValue(makeMockRoomState([membershipTemplate], mockRoom.roomId, undefined));
|
.mockReturnValue(makeMockRoomState([membershipTemplate], mockRoom.roomId));
|
||||||
sess.onMembershipUpdate();
|
sess.onMembershipUpdate();
|
||||||
|
|
||||||
jest.advanceTimersByTime(10000);
|
jest.advanceTimersByTime(10000);
|
||||||
@@ -977,7 +994,7 @@ describe("MatrixRTCSession", () => {
|
|||||||
|
|
||||||
mockRoom.getLiveTimeline().getState = jest
|
mockRoom.getLiveTimeline().getState = jest
|
||||||
.fn()
|
.fn()
|
||||||
.mockReturnValue(makeMockRoomState([membershipTemplate, member2], mockRoom.roomId, undefined));
|
.mockReturnValue(makeMockRoomState([membershipTemplate, member2], mockRoom.roomId));
|
||||||
sess.onMembershipUpdate();
|
sess.onMembershipUpdate();
|
||||||
|
|
||||||
await new Promise((resolve) => {
|
await new Promise((resolve) => {
|
||||||
@@ -1009,9 +1026,7 @@ describe("MatrixRTCSession", () => {
|
|||||||
const onMembershipsChanged = jest.fn();
|
const onMembershipsChanged = jest.fn();
|
||||||
sess.on(MatrixRTCSessionEvent.MembershipsChanged, onMembershipsChanged);
|
sess.on(MatrixRTCSessionEvent.MembershipsChanged, onMembershipsChanged);
|
||||||
|
|
||||||
mockRoom.getLiveTimeline().getState = jest
|
mockRoom.getLiveTimeline().getState = jest.fn().mockReturnValue(makeMockRoomState([], mockRoom.roomId));
|
||||||
.fn()
|
|
||||||
.mockReturnValue(makeMockRoomState([], mockRoom.roomId, undefined));
|
|
||||||
sess.onMembershipUpdate();
|
sess.onMembershipUpdate();
|
||||||
|
|
||||||
expect(onMembershipsChanged).toHaveBeenCalled();
|
expect(onMembershipsChanged).toHaveBeenCalled();
|
||||||
@@ -1021,7 +1036,7 @@ describe("MatrixRTCSession", () => {
|
|||||||
jest.useFakeTimers();
|
jest.useFakeTimers();
|
||||||
try {
|
try {
|
||||||
const membership = Object.assign({}, membershipTemplate);
|
const membership = Object.assign({}, membershipTemplate);
|
||||||
const mockRoom = makeMockRoom([membership], 0);
|
const mockRoom = makeMockRoom([membership]);
|
||||||
|
|
||||||
sess = MatrixRTCSession.roomSessionForRoom(client, mockRoom);
|
sess = MatrixRTCSession.roomSessionForRoom(client, mockRoom);
|
||||||
const membershipObject = sess.memberships[0];
|
const membershipObject = sess.memberships[0];
|
||||||
@@ -1049,7 +1064,7 @@ describe("MatrixRTCSession", () => {
|
|||||||
expires: 1000,
|
expires: 1000,
|
||||||
}),
|
}),
|
||||||
];
|
];
|
||||||
const mockRoomNoExpired = makeMockRoom(mockMemberships, 0);
|
const mockRoomNoExpired = makeMockRoom(mockMemberships);
|
||||||
|
|
||||||
sess = MatrixRTCSession.roomSessionForRoom(client, mockRoomNoExpired);
|
sess = MatrixRTCSession.roomSessionForRoom(client, mockRoomNoExpired);
|
||||||
|
|
||||||
@@ -1088,6 +1103,7 @@ describe("MatrixRTCSession", () => {
|
|||||||
it("fills in created_ts for other memberships on update", () => {
|
it("fills in created_ts for other memberships on update", () => {
|
||||||
client.sendStateEvent = jest.fn();
|
client.sendStateEvent = jest.fn();
|
||||||
jest.useFakeTimers();
|
jest.useFakeTimers();
|
||||||
|
jest.setSystemTime(1000);
|
||||||
const mockRoom = makeMockRoom([
|
const mockRoom = makeMockRoom([
|
||||||
Object.assign({}, membershipTemplate, {
|
Object.assign({}, membershipTemplate, {
|
||||||
device_id: "OTHERDEVICE",
|
device_id: "OTHERDEVICE",
|
||||||
|
@@ -20,10 +20,10 @@ import { randomString } from "../../../src/randomstring";
|
|||||||
|
|
||||||
type MembershipData = CallMembershipData[] | SessionMembershipData;
|
type MembershipData = CallMembershipData[] | SessionMembershipData;
|
||||||
|
|
||||||
export function makeMockRoom(membershipData: MembershipData, localAge: number | null = null): Room {
|
export function makeMockRoom(membershipData: MembershipData): Room {
|
||||||
const roomId = randomString(8);
|
const roomId = randomString(8);
|
||||||
// Caching roomState here so it does not get recreated when calling `getLiveTimeline.getState()`
|
// Caching roomState here so it does not get recreated when calling `getLiveTimeline.getState()`
|
||||||
const roomState = makeMockRoomState(membershipData, roomId, localAge);
|
const roomState = makeMockRoomState(membershipData, roomId);
|
||||||
return {
|
return {
|
||||||
roomId: roomId,
|
roomId: roomId,
|
||||||
hasMembershipState: jest.fn().mockReturnValue(true),
|
hasMembershipState: jest.fn().mockReturnValue(true),
|
||||||
@@ -34,8 +34,8 @@ export function makeMockRoom(membershipData: MembershipData, localAge: number |
|
|||||||
} as unknown as Room;
|
} as unknown as Room;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function makeMockRoomState(membershipData: MembershipData, roomId: string, localAge: number | null = null) {
|
export function makeMockRoomState(membershipData: MembershipData, roomId: string) {
|
||||||
const event = mockRTCEvent(membershipData, roomId, localAge);
|
const event = mockRTCEvent(membershipData, roomId);
|
||||||
return {
|
return {
|
||||||
on: jest.fn(),
|
on: jest.fn(),
|
||||||
off: jest.fn(),
|
off: jest.fn(),
|
||||||
@@ -57,7 +57,7 @@ export function makeMockRoomState(membershipData: MembershipData, roomId: string
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function mockRTCEvent(membershipData: MembershipData, roomId: string, localAge: number | null): MatrixEvent {
|
export function mockRTCEvent(membershipData: MembershipData, roomId: string): MatrixEvent {
|
||||||
return {
|
return {
|
||||||
getType: jest.fn().mockReturnValue(EventType.GroupCallMemberPrefix),
|
getType: jest.fn().mockReturnValue(EventType.GroupCallMemberPrefix),
|
||||||
getContent: jest.fn().mockReturnValue(
|
getContent: jest.fn().mockReturnValue(
|
||||||
@@ -68,8 +68,7 @@ export function mockRTCEvent(membershipData: MembershipData, roomId: string, loc
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
getSender: jest.fn().mockReturnValue("@mock:user.example"),
|
getSender: jest.fn().mockReturnValue("@mock:user.example"),
|
||||||
getTs: jest.fn().mockReturnValue(1000),
|
getTs: jest.fn().mockReturnValue(Date.now()),
|
||||||
localTimestamp: Date.now() - (localAge ?? 10),
|
|
||||||
getRoomId: jest.fn().mockReturnValue(roomId),
|
getRoomId: jest.fn().mockReturnValue(roomId),
|
||||||
sender: {
|
sender: {
|
||||||
userId: "@mock:user.example",
|
userId: "@mock:user.example",
|
||||||
|
@@ -156,8 +156,14 @@ export class CallMembership {
|
|||||||
return this.membershipData.created_ts ?? this.parentEvent.getTs();
|
return this.membershipData.created_ts ?? this.parentEvent.getTs();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the absolute expiry time of the membership if applicable to this membership type.
|
||||||
|
* @returns The absolute expiry time of the membership as a unix timestamp in milliseconds or undefined if not applicable
|
||||||
|
*/
|
||||||
public getAbsoluteExpiry(): number | undefined {
|
public getAbsoluteExpiry(): number | undefined {
|
||||||
|
// if the membership is not a legacy membership, we assume it is MSC4143
|
||||||
if (!isLegacyCallMembershipData(this.membershipData)) return undefined;
|
if (!isLegacyCallMembershipData(this.membershipData)) return undefined;
|
||||||
|
|
||||||
if ("expires" in this.membershipData) {
|
if ("expires" in this.membershipData) {
|
||||||
// we know createdTs exists since we already do the isLegacyCallMembershipData check
|
// we know createdTs exists since we already do the isLegacyCallMembershipData check
|
||||||
return this.createdTs() + this.membershipData.expires;
|
return this.createdTs() + this.membershipData.expires;
|
||||||
@@ -167,9 +173,15 @@ export class CallMembership {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// gets the expiry time of the event, converted into the device's local time
|
/**
|
||||||
|
* Gets the expiry time of the event, converted into the device's local time.
|
||||||
|
* @deprecated This function has been observed returning bad data and is no longer used by MatrixRTC.
|
||||||
|
* @returns The local expiry time of the membership as a unix timestamp in milliseconds or undefined if not applicable
|
||||||
|
*/
|
||||||
public getLocalExpiry(): number | undefined {
|
public getLocalExpiry(): number | undefined {
|
||||||
|
// if the membership is not a legacy membership, we assume it is MSC4143
|
||||||
if (!isLegacyCallMembershipData(this.membershipData)) return undefined;
|
if (!isLegacyCallMembershipData(this.membershipData)) return undefined;
|
||||||
|
|
||||||
if ("expires" in this.membershipData) {
|
if ("expires" in this.membershipData) {
|
||||||
// we know createdTs exists since we already do the isLegacyCallMembershipData check
|
// we know createdTs exists since we already do the isLegacyCallMembershipData check
|
||||||
const relativeCreationTime = this.parentEvent.getTs() - this.createdTs();
|
const relativeCreationTime = this.parentEvent.getTs() - this.createdTs();
|
||||||
@@ -184,10 +196,24 @@ export class CallMembership {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns The number of milliseconds until the membership expires or undefined if applicable
|
||||||
|
*/
|
||||||
public getMsUntilExpiry(): number | undefined {
|
public getMsUntilExpiry(): number | undefined {
|
||||||
if (isLegacyCallMembershipData(this.membershipData)) return this.getLocalExpiry()! - Date.now();
|
if (isLegacyCallMembershipData(this.membershipData)) {
|
||||||
|
// Assume that local clock is sufficiently in sync with other clocks in the distributed system.
|
||||||
|
// We used to try and adjust for the local clock being skewed, but there are cases where this is not accurate.
|
||||||
|
// The current implementation allows for the local clock to be -infinity to +MatrixRTCSession.MEMBERSHIP_EXPIRY_TIME/2
|
||||||
|
return this.getAbsoluteExpiry()! - Date.now();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assumed to be MSC4143
|
||||||
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns true if the membership has expired, otherwise false
|
||||||
|
*/
|
||||||
public isExpired(): boolean {
|
public isExpired(): boolean {
|
||||||
if (isLegacyCallMembershipData(this.membershipData)) return this.getMsUntilExpiry()! <= 0;
|
if (isLegacyCallMembershipData(this.membershipData)) return this.getMsUntilExpiry()! <= 0;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user