From 6de27108417327c04ffe3a4bb552cdaf86f76354 Mon Sep 17 00:00:00 2001 From: Fedor Indutny <79877362+indutny-signal@users.noreply.github.com> Date: Fri, 4 Feb 2022 13:42:20 -0800 Subject: [PATCH] Use new server params for group log fetch --- ts/groups.ts | 22 +++++++++++++++-- ts/textsecure/SendMessage.ts | 7 +++--- ts/textsecure/WebAPI.ts | 47 +++++++++++++++++++++++++++--------- 3 files changed, 59 insertions(+), 17 deletions(-) diff --git a/ts/groups.ts b/ts/groups.ts index 0c4ac6af25..3eb8b75229 100644 --- a/ts/groups.ts +++ b/ts/groups.ts @@ -2541,7 +2541,16 @@ export async function respondToGroupV2Migration({ logId: `getGroupLog/${logId}`, publicParams, secretParams, - request: (sender, options) => sender.getGroupLog(0, options), + request: (sender, options) => + sender.getGroupLog( + { + startVersion: 0, + includeFirstState: true, + includeLastState: false, + maxSupportedChangeEpoch: SUPPORTED_CHANGE_EPOCH, + }, + options + ), }); // Attempt to start with the first group state, only later processing future updates @@ -3276,6 +3285,7 @@ async function getGroupDelta({ }); const currentRevision = group.revision; + const isFirstFetch = !isNumber(currentRevision); let revisionToFetch = isNumber(currentRevision) ? currentRevision + 1 : undefined; @@ -3284,7 +3294,15 @@ async function getGroupDelta({ const changes: Array = []; do { // eslint-disable-next-line no-await-in-loop - response = await sender.getGroupLog(revisionToFetch, options); + response = await sender.getGroupLog( + { + startVersion: revisionToFetch, + includeFirstState: isFirstFetch, + includeLastState: false, + maxSupportedChangeEpoch: SUPPORTED_CHANGE_EPOCH, + }, + options + ); changes.push(response.changes); if (response.end) { revisionToFetch = response.end + 1; diff --git a/ts/textsecure/SendMessage.ts b/ts/textsecure/SendMessage.ts index 5c13a8b2c7..d2ec55873f 100644 --- a/ts/textsecure/SendMessage.ts +++ b/ts/textsecure/SendMessage.ts @@ -28,6 +28,7 @@ import type * as Attachment from '../types/Attachment'; import type { UUID, UUIDStringType } from '../types/UUID'; import type { ChallengeType, + GetGroupLogOptionsType, GroupCredentialsType, GroupLogResponseType, MultiRecipient200ResponseType, @@ -2134,10 +2135,10 @@ export default class MessageSender { } async getGroupLog( - startVersion: number | undefined, - options: Readonly + options: GetGroupLogOptionsType, + credentials: GroupCredentialsType ): Promise { - return this.server.getGroupLog(startVersion, options); + return this.server.getGroupLog(options, credentials); } async getGroupAvatar(key: string): Promise { diff --git a/ts/textsecure/WebAPI.ts b/ts/textsecure/WebAPI.ts index bef2690b5d..6cad9a03f9 100644 --- a/ts/textsecure/WebAPI.ts +++ b/ts/textsecure/WebAPI.ts @@ -681,6 +681,12 @@ export type GroupCredentialsType = { groupPublicParamsHex: string; authCredentialPresentationHex: string; }; +export type GetGroupLogOptionsType = Readonly<{ + startVersion: number | undefined; + includeFirstState: boolean; + includeLastState: boolean; + maxSupportedChangeEpoch: number; +}>; export type GroupLogResponseType = { currentRevision?: number; start?: number; @@ -804,8 +810,8 @@ export type WebAPIType = { options: GroupCredentialsType ) => Promise; getGroupLog: ( - startVersion: number | undefined, - options: GroupCredentialsType + options: GetGroupLogOptionsType, + credentials: GroupCredentialsType ) => Promise; getIceServers: () => Promise; getKeysForIdentifier: ( @@ -1071,7 +1077,7 @@ export function initialize({ let password = initialPassword; const PARSE_RANGE_HEADER = /\/(\d+)$/; const PARSE_GROUP_LOG_RANGE_HEADER = - /$versions (\d{1,10})-(\d{1,10})\/(d{1,10})/; + /^versions\s+(\d{1,10})-(\d{1,10})\/(\d{1,10})/; let activeRegistration: ExplodePromiseResultType | undefined; @@ -2603,14 +2609,21 @@ export function initialize({ } async function getGroupLog( - startVersion: number | undefined, - options: GroupCredentialsType + options: GetGroupLogOptionsType, + credentials: GroupCredentialsType ): Promise { const basicAuth = generateGroupAuth( - options.groupPublicParamsHex, - options.authCredentialPresentationHex + credentials.groupPublicParamsHex, + credentials.authCredentialPresentationHex ); + const { + startVersion, + includeFirstState, + includeLastState, + maxSupportedChangeEpoch, + } = options; + // If we don't know starting revision - fetch it from the server if (startVersion === undefined) { const { data: joinedData } = await _ajax({ @@ -2624,7 +2637,13 @@ export function initialize({ const { joinedAtVersion } = Proto.Member.decode(joinedData); - return getGroupLog(joinedAtVersion, options); + return getGroupLog( + { + ...options, + startVersion: joinedAtVersion, + }, + credentials + ); } const withDetails = await _ajax({ @@ -2634,7 +2653,11 @@ export function initialize({ host: storageUrl, httpType: 'GET', responseType: 'byteswithdetails', - urlParameters: `/${startVersion}`, + urlParameters: + `/${startVersion}?` + + `includeFirstState=${Boolean(includeFirstState)}&` + + `includeLastState=${Boolean(includeLastState)}&` + + `maxSupportedChangeEpoch=${Number(maxSupportedChangeEpoch)}`, }); const { data, response } = withDetails; const changes = Proto.GroupChanges.decode(data); @@ -2643,9 +2666,9 @@ export function initialize({ const range = response.headers.get('Content-Range'); const match = PARSE_GROUP_LOG_RANGE_HEADER.exec(range || ''); - const start = match ? parseInt(match[0], 10) : undefined; - const end = match ? parseInt(match[1], 10) : undefined; - const currentRevision = match ? parseInt(match[2], 10) : undefined; + const start = match ? parseInt(match[1], 10) : undefined; + const end = match ? parseInt(match[2], 10) : undefined; + const currentRevision = match ? parseInt(match[3], 10) : undefined; if ( match &&