Add support for call link epochs

Co-authored-by: trevor-signal <trevor@signal.org>
This commit is contained in:
emir-signal
2025-08-07 15:12:56 -04:00
committed by GitHub
parent ee45891d35
commit ebf2892039
36 changed files with 393 additions and 86 deletions

View File

@@ -20,6 +20,7 @@ import {
callLinkFromRecord,
defunctCallLinkToRecord,
defunctCallLinkFromRecord,
toEpochBytes,
} from '../../util/callLinksRingrtc';
import type { ReadableDB, WritableDB } from '../Interface';
import { sql } from '../util';
@@ -62,7 +63,6 @@ export function getCallLinkRecordByRoomId(
const row = db.prepare('SELECT * FROM callLinks WHERE roomId = $roomId').get({
roomId,
});
if (!row) {
return undefined;
}
@@ -92,6 +92,7 @@ function _insertCallLink(db: WritableDB, callLink: CallLinkType): void {
INSERT INTO callLinks (
roomId,
rootKey,
epoch,
adminKey,
name,
restrictions,
@@ -104,6 +105,7 @@ function _insertCallLink(db: WritableDB, callLink: CallLinkType): void {
) VALUES (
$roomId,
$rootKey,
$epoch,
$adminKey,
$name,
$restrictions,
@@ -132,14 +134,17 @@ export function insertOrUpdateCallLinkFromSync(
db: WritableDB,
callLink: CallLinkType
): InsertOrUpdateCallLinkFromSyncResult {
const { roomId, adminKey } = callLink;
const { roomId, epoch, adminKey } = callLink;
return db.transaction(() => {
const existingCallLink = getCallLinkByRoomId(db, roomId);
if (existingCallLink) {
if (adminKey && adminKey !== existingCallLink.adminKey) {
updateCallLinkAdminKeyByRoomId(db, roomId, adminKey);
if (
(adminKey && adminKey !== existingCallLink.adminKey) ||
epoch !== existingCallLink.epoch
) {
updateCallLinkEpochAndAdminKeyByRoomId(db, roomId, epoch, adminKey);
return {
callLink: { ...existingCallLink, adminKey },
callLink: { ...existingCallLink, adminKey, epoch },
inserted: false,
updated: true,
};
@@ -167,6 +172,7 @@ export function updateCallLink(db: WritableDB, callLink: CallLinkType): void {
`
UPDATE callLinks
SET
epoch = $epoch,
adminKey = $adminKey,
name = $name,
restrictions = $restrictions,
@@ -206,19 +212,59 @@ export function updateCallLinkState(
return callLinkFromRecord(parseUnknown(callLinkRecordSchema, row));
}
export function updateCallLinkAdminKeyByRoomId(
export function updateCallLinkStateAndEpoch(
db: WritableDB,
roomId: string,
adminKey: string
): void {
const adminKeyBytes = toAdminKeyBytes(adminKey);
db.prepare(
`
callLinkState: CallLinkStateType,
epoch: string | null
): CallLinkType {
const { name, restrictions, expiration, revoked } = callLinkState;
const restrictionsValue = parseStrict(
callLinkRestrictionsSchema,
restrictions
);
const epochBytes = epoch ? toEpochBytes(epoch) : null;
const [query, params] = sql`
UPDATE callLinks
SET adminKey = $adminKeyBytes
WHERE roomId = $roomId;
`
).run({ roomId, adminKeyBytes });
SET
name = ${name},
epoch = ${epochBytes},
restrictions = ${restrictionsValue},
expiration = ${expiration},
revoked = ${revoked ? 1 : 0}
WHERE roomId = ${roomId}
RETURNING *;
`;
const row: unknown = db.prepare(query).get(params);
strictAssert(row, 'Expected row to be returned');
return callLinkFromRecord(parseUnknown(callLinkRecordSchema, row));
}
export function updateCallLinkEpochAndAdminKeyByRoomId(
db: WritableDB,
roomId: string,
epoch: string | null,
adminKey: string | null
): void {
const epochBytes = epoch ? toEpochBytes(epoch) : null;
if (adminKey) {
const adminKeyBytes = toAdminKeyBytes(adminKey);
db.prepare(
`
UPDATE callLinks
SET adminKey = $adminKeyBytes, epoch = $epochBytes
WHERE roomId = $roomId;
`
).run({ roomId, epochBytes, adminKeyBytes });
} else {
db.prepare(
`
UPDATE callLinks
SET epoch = $epochBytes
WHERE roomId = $roomId;
`
).run({ roomId, epochBytes });
}
}
function assertRoomIdMatchesRootKey(roomId: string, rootKey: string): void {
@@ -466,6 +512,7 @@ export function insertDefunctCallLink(
INSERT INTO defunctCallLinks (
roomId,
rootKey,
epoch,
adminKey,
storageID,
storageVersion,
@@ -474,6 +521,7 @@ export function insertDefunctCallLink(
) VALUES (
$roomId,
$rootKey,
$epoch,
$adminKey,
$storageID,
$storageVersion,