mirror of
https://github.com/vector-im/hydrogen-web.git
synced 2024-11-20 03:25:52 +01:00
Add support for m.expires_ts WIP
This commit is contained in:
parent
1d1103a3c7
commit
af433aa762
@ -503,6 +503,7 @@ export class Session {
|
||||
room.dispose();
|
||||
}
|
||||
this._rooms = undefined;
|
||||
this.callHandler.dispose();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -54,6 +54,7 @@ export class CallHandler implements RoomStateHandler {
|
||||
private roomMemberToCallIds: Map<string, Set<string>> = new Map();
|
||||
private groupCallOptions: GroupCallOptions;
|
||||
private sessionId = makeId("s");
|
||||
private memberStateExpirationTimers: Map<string, number> = new Map();
|
||||
|
||||
constructor(private readonly options: Options) {
|
||||
this.groupCallOptions = Object.assign({}, this.options, {
|
||||
@ -217,6 +218,29 @@ export class CallHandler implements RoomStateHandler {
|
||||
const userId = event.state_key;
|
||||
const roomMemberKey = getRoomMemberKey(roomId, userId)
|
||||
const calls = event.content["m.calls"] ?? [];
|
||||
|
||||
const now = Date.now();
|
||||
const expiresAt = typeof event.content["m.expires_ts"] === "number" ? event.content["m.expires_ts"] : -Infinity;
|
||||
|
||||
console.log(`expiresAt ${expiresAt} now ${now}`, event.content);
|
||||
|
||||
if (expiresAt <= now) {
|
||||
console.log(`Initial ${roomId} ${member.userId} expired`);
|
||||
return;
|
||||
}
|
||||
|
||||
clearTimeout(this.memberStateExpirationTimers.get(member.userId));
|
||||
|
||||
this.memberStateExpirationTimers.set(member.userId, setTimeout(() => {
|
||||
console.log(`Timeout ${roomId} ${userId} expired`)
|
||||
for (const callId of calls.map(call => call["m.call_id"])) {
|
||||
const groupCall = this._calls.get(callId);
|
||||
groupCall?.removeMembership(userId, log);
|
||||
}
|
||||
|
||||
this.roomMemberToCallIds.delete(roomMemberKey);
|
||||
}, event.content["m.expires_ts"] - Date.now()));
|
||||
|
||||
const eventTimestamp = event.origin_server_ts;
|
||||
for (const call of calls) {
|
||||
const callId = call["m.call_id"];
|
||||
@ -242,5 +266,12 @@ export class CallHandler implements RoomStateHandler {
|
||||
this.roomMemberToCallIds.set(roomMemberKey, newCallIdsMemberOf);
|
||||
}
|
||||
}
|
||||
|
||||
dispose() {
|
||||
for (const [userId] of this.memberStateExpirationTimers) {
|
||||
clearTimeout(this.memberStateExpirationTimers.get(userId));
|
||||
this.memberStateExpirationTimers.delete(userId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,6 +34,7 @@ export interface CallMembership {
|
||||
|
||||
export interface CallMemberContent {
|
||||
["m.calls"]: CallMembership[];
|
||||
["m.expires_ts"]?: number
|
||||
}
|
||||
|
||||
export enum SDPStreamMetadataPurpose {
|
||||
|
@ -33,6 +33,8 @@ import type {EncryptedMessage} from "../../e2ee/olm/Encryption";
|
||||
import type {ILogItem, ILogger} from "../../../logging/types";
|
||||
import type {Storage} from "../../storage/idb/Storage";
|
||||
|
||||
const CALL_MEMBER_STATE_TIMEOUT = 1000 * 60 * 60; // 1 hour
|
||||
|
||||
export enum GroupCallState {
|
||||
Fledgling = "fledgling",
|
||||
Creating = "creating",
|
||||
@ -83,6 +85,7 @@ export class GroupCall extends EventEmitter<{change: never}> {
|
||||
|
||||
private _deviceIndex?: number;
|
||||
private _eventTimestamp?: number;
|
||||
private resendMemberStateTimer?: number;
|
||||
|
||||
constructor(
|
||||
public readonly id: string,
|
||||
@ -161,9 +164,11 @@ export class GroupCall extends EventEmitter<{change: never}> {
|
||||
this._state = GroupCallState.Joining;
|
||||
this.emitChange();
|
||||
await log.wrap("update member state", async log => {
|
||||
const memberContent = await this._createJoinPayload();
|
||||
const memberContent = await this._createMemberStateEventPayload();
|
||||
this._eventTimestamp = Date.now();
|
||||
log.set("payload", memberContent);
|
||||
// send m.call.member state event
|
||||
console.log("sending", memberContent);
|
||||
const request = this.options.hsApi.sendState(this.roomId, EventType.GroupCallMember, this.options.ownUserId, memberContent, {log});
|
||||
await request.response();
|
||||
this.emitChange();
|
||||
@ -173,6 +178,24 @@ export class GroupCall extends EventEmitter<{change: never}> {
|
||||
this.connectToMember(member, joinedData, log);
|
||||
}
|
||||
});
|
||||
|
||||
clearTimeout(this.resendMemberStateTimer);
|
||||
|
||||
this.resendMemberStateTimer = setTimeout(this.resendMemberStateEvent, CALL_MEMBER_STATE_TIMEOUT * 3 / 4);
|
||||
}
|
||||
|
||||
async resendMemberStateEvent() {
|
||||
await this.options.logger.run("resend member state event", async log => {
|
||||
const memberContent = await this._createMemberStateEventPayload();
|
||||
this._eventTimestamp = Date.now();
|
||||
log.set("payload", memberContent);
|
||||
// send m.call.member state event
|
||||
const request = this.options.hsApi.sendState(this.roomId, EventType.GroupCallMember, this.options.ownUserId, memberContent, {log});
|
||||
await request.response();
|
||||
this.emitChange();
|
||||
});
|
||||
|
||||
this.resendMemberStateTimer = setTimeout(this.resendMemberStateEvent, CALL_MEMBER_STATE_TIMEOUT * 3 / 4);
|
||||
}
|
||||
|
||||
async setMedia(localMedia: LocalMedia): Promise<void> {
|
||||
@ -425,6 +448,7 @@ export class GroupCall extends EventEmitter<{change: never}> {
|
||||
}
|
||||
this._state = GroupCallState.Created;
|
||||
}
|
||||
clearTimeout(this.resendMemberStateTimer);
|
||||
this.joinedData?.dispose();
|
||||
this.joinedData = undefined;
|
||||
this.emitChange();
|
||||
@ -476,13 +500,17 @@ export class GroupCall extends EventEmitter<{change: never}> {
|
||||
}
|
||||
}
|
||||
|
||||
private async _createJoinPayload() {
|
||||
private async _createMemberStateEventPayload() {
|
||||
const {storage} = this.options;
|
||||
const txn = await storage.readTxn([storage.storeNames.roomState]);
|
||||
const stateEvent = await txn.roomState.get(this.roomId, EventType.GroupCallMember, this.options.ownUserId);
|
||||
const expiresAt = Date.now() + CALL_MEMBER_STATE_TIMEOUT;
|
||||
const stateContent = stateEvent?.event?.content ?? {
|
||||
["m.calls"]: []
|
||||
["m.calls"]: [],
|
||||
};
|
||||
|
||||
stateContent["m.expires_ts"] = expiresAt;
|
||||
|
||||
const callsInfo = stateContent["m.calls"];
|
||||
let callInfo = callsInfo.find(c => c["m.call_id"] === this.id);
|
||||
if (!callInfo) {
|
||||
@ -500,7 +528,8 @@ export class GroupCall extends EventEmitter<{change: never}> {
|
||||
});
|
||||
|
||||
this._deviceIndex = callInfo["m.devices"].length;
|
||||
this._eventTimestamp = Date.now();
|
||||
|
||||
console.log(`sent member state event expiresAt ${expiresAt}`);
|
||||
|
||||
return stateContent;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user