Removes groupv1 protos

This commit is contained in:
Josh Perez 2023-07-26 13:49:27 -04:00 committed by GitHub
parent 6c70cd450b
commit 8aac997b4f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 21 additions and 373 deletions

View file

@ -189,7 +189,7 @@
"@electron/fuses": "1.5.0",
"@formatjs/intl": "2.6.7",
"@mixer/parallel-prettier": "2.0.3",
"@signalapp/mock-server": "3.2.1",
"@signalapp/mock-server": "3.2.3",
"@storybook/addon-a11y": "6.5.6",
"@storybook/addon-actions": "6.5.6",
"@storybook/addon-controls": "6.5.6",

View file

@ -315,10 +315,10 @@ message DataMessage {
STRIKETHROUGH = 4;
MONOSPACE = 5;
}
optional uint32 start = 1;
optional uint32 length = 2;
oneof associatedValue {
string mentionUuid = 3;
Style style = 4;
@ -493,10 +493,6 @@ message SyncMessage {
optional bool complete = 2 [default = false];
}
message Groups {
optional AttachmentPointer blob = 1;
}
message Blocked {
repeated string numbers = 1;
repeated string uuids = 3;
@ -507,7 +503,7 @@ message SyncMessage {
enum Type {
UNKNOWN = 0;
CONTACTS = 1;
GROUPS = 2;
reserved /* GROUPS */ 2;
BLOCKED = 3;
CONFIGURATION = 4;
KEYS = 5;
@ -623,7 +619,7 @@ message SyncMessage {
optional Sent sent = 1;
optional Contacts contacts = 2;
optional Groups groups = 3;
reserved /* groups */ 3;
optional Request request = 4;
repeated Read read = 5;
optional Blocked blocked = 6;
@ -695,29 +691,6 @@ message ContactDetails {
optional uint32 inboxPosition = 10;
}
message GroupDetails {
message Avatar {
optional string contentType = 1;
optional uint32 length = 2;
}
message Member {
optional string uuid = 1;
optional string e164 = 2;
}
optional bytes id = 1;
optional string name = 2;
repeated string membersE164 = 3;
repeated Member members = 9;
optional Avatar avatar = 4;
optional bool active = 5 [default = true];
optional uint32 expireTimer = 6;
optional string color = 7;
optional bool blocked = 8;
optional uint32 inboxPosition = 10;
}
message PniSignatureMessage {
optional bytes pni = 1;
// Signature *by* the PNI identity key *of* the ACI identity key

View file

@ -22,7 +22,6 @@ import createTaskWithTimeout, {
} from './textsecure/TaskWithTimeout';
import type {
MessageAttributesType,
ConversationAttributesType,
ReactionAttributesType,
} from './model-types.d';
import * as Bytes from './Bytes';
@ -87,7 +86,6 @@ import type {
EnvelopeUnsealedEvent,
ErrorEvent,
FetchLatestEvent,
GroupEvent,
InvalidPlaintextEvent,
KeysEvent,
MessageEvent,
@ -108,7 +106,7 @@ import type {
import type { WebAPIType } from './textsecure/WebAPI';
import * as KeyChangeListener from './textsecure/KeyChangeListener';
import { UpdateKeysListener } from './textsecure/UpdateKeysListener';
import { isDirectConversation, isGroupV2 } from './util/whatTypeOfConversation';
import { isDirectConversation } from './util/whatTypeOfConversation';
import { BackOff, FIBONACCI_TIMEOUTS } from './util/BackOff';
import { AppViewType } from './state/ducks/app';
import type { BadgesStateType } from './state/ducks/badges';
@ -137,7 +135,6 @@ import { ReadStatus } from './messages/MessageReadStatus';
import type { SendStateByConversationId } from './messages/MessageSendState';
import { SendStatus } from './messages/MessageSendState';
import * as AttachmentDownloads from './messageModifiers/AttachmentDownloads';
import * as Conversation from './types/Conversation';
import * as Stickers from './types/Stickers';
import * as Errors from './types/errors';
import { SignalService as Proto } from './protobuf';
@ -359,14 +356,6 @@ export async function startApp(): Promise<void> {
'contactSync',
queuedEventListener(onContactSync)
);
messageReceiver.addEventListener(
'group',
queuedEventListener(onGroupReceived)
);
messageReceiver.addEventListener(
'groupSync',
queuedEventListener(onGroupSyncComplete)
);
messageReceiver.addEventListener(
'sent',
queuedEventListener(onSentMessage, false)
@ -573,12 +562,7 @@ export async function startApp(): Promise<void> {
window.setImmediate = window.nodeSetImmediate;
const { Message } = window.Signal.Types;
const {
upgradeMessageSchema,
writeNewAttachmentData,
deleteAttachmentData,
doesAttachmentExist,
} = window.Signal.Migrations;
const { upgradeMessageSchema } = window.Signal.Migrations;
log.info('background page reloaded');
log.info('environment:', window.getEnvironment());
@ -1954,11 +1938,10 @@ export async function startApp(): Promise<void> {
MessageSender.getRequestConfigurationSyncMessage()
),
singleProtoJobQueue.add(MessageSender.getRequestBlockSyncMessage()),
singleProtoJobQueue.add(MessageSender.getRequestGroupSyncMessage()),
runStorageService(),
singleProtoJobQueue.add(
MessageSender.getRequestContactSyncMessage()
),
runStorageService(),
]);
} catch (error) {
log.error(
@ -2311,85 +2294,6 @@ export async function startApp(): Promise<void> {
});
}
async function onGroupSyncComplete(): Promise<void> {
log.info('onGroupSyncComplete');
await window.storage.put('synced_at', Date.now());
}
// Note: this handler is only for v1 groups received via 'group sync' messages
async function onGroupReceived(ev: GroupEvent): Promise<void> {
const details = ev.groupDetails;
const { id } = details;
const conversation = await window.ConversationController.getOrCreateAndWait(
id,
'group'
);
if (isGroupV2(conversation.attributes)) {
log.warn('Got group sync for v2 group: ', conversation.idForLogging());
return;
}
const memberConversations = details.membersE164.map(e164 =>
window.ConversationController.getOrCreate(e164, 'private')
);
const members = memberConversations.map(c => c.get('id'));
const updates: Partial<ConversationAttributesType> = {
name: details.name,
members,
type: 'group',
inbox_position: details.inboxPosition,
};
if (details.active) {
updates.left = false;
} else {
updates.left = true;
}
if (details.blocked) {
conversation.block();
} else {
conversation.unblock();
}
conversation.set(updates);
// Update the conversation avatar only if new avatar exists and hash differs
const { avatar } = details;
if (avatar && avatar.data) {
const newAttributes = await Conversation.maybeUpdateAvatar(
conversation.attributes,
avatar.data,
{
writeNewAttachmentData,
deleteAttachmentData,
doesAttachmentExist,
}
);
conversation.set(newAttributes);
}
window.Signal.Data.updateConversation(conversation.attributes);
const { expireTimer } = details;
const isValidExpireTimer = typeof expireTimer === 'number';
if (!isValidExpireTimer) {
return;
}
await conversation.updateExpirationTimer(expireTimer, {
// Note: because it's our conversationId, this notification will be marked read. But
// setting this will make 'isSetByOther' check true.
source: window.ConversationController.getOurConversationId(),
fromSync: true,
receivedAt: ev.receivedAtCounter,
reason: 'group sync',
});
}
// Received:
async function handleMessageReceivedProfileUpdate({
data,

View file

@ -6,7 +6,7 @@ import protobuf from '../protobuf/wrap';
import * as Bytes from '../Bytes';
import { SignalService as Proto } from '../protobuf';
import { ContactBuffer, GroupBuffer } from '../textsecure/ContactsParser';
import { ContactBuffer } from '../textsecure/ContactsParser';
const { Writer } = protobuf;
@ -70,58 +70,4 @@ describe('ContactsParser', () => {
assert.strictEqual(count, 3);
});
});
describe('GroupBuffer', () => {
function getTestBuffer(): Uint8Array {
const avatarBuffer = generateAvatar();
const groupInfoBuffer = Proto.GroupDetails.encode({
id: new Uint8Array([1, 3, 3, 7]),
name: 'Hackers',
membersE164: ['cereal', 'burn', 'phreak', 'joey'],
avatar: { contentType: 'image/jpeg', length: avatarBuffer.length },
}).finish();
const writer = new Writer();
writer.bytes(groupInfoBuffer);
const prefixedGroup = writer.finish();
const chunks: Array<Uint8Array> = [];
for (let i = 0; i < 3; i += 1) {
chunks.push(prefixedGroup);
chunks.push(avatarBuffer);
}
return Bytes.concatenate(chunks);
}
it('parses an array buffer of groups', () => {
const bytes = getTestBuffer();
const groupBuffer = new GroupBuffer(bytes);
let group = groupBuffer.next();
let count = 0;
while (group !== undefined) {
count += 1;
assert.strictEqual(group.name, 'Hackers');
assert.deepEqual(group.id, new Uint8Array([1, 3, 3, 7]));
assert.sameMembers(group.membersE164, [
'cereal',
'burn',
'phreak',
'joey',
]);
assert.strictEqual(group.avatar?.contentType, 'image/jpeg');
assert.strictEqual(group.avatar?.length, 255);
assert.strictEqual(group.avatar?.data.byteLength, 255);
const avatarBytes = new Uint8Array(
group.avatar?.data || new Uint8Array(0)
);
for (let j = 0; j < 255; j += 1) {
assert.strictEqual(avatarBytes[j], j);
}
group = groupBuffer.next();
}
assert.strictEqual(count, 3);
});
});
});

View file

@ -72,7 +72,7 @@ describe('editing', function needsName() {
await bootstrap.teardown();
});
it('handles outgoing edited messages phone -> desktop', async () => {
it('handles outgoing edited messages phone to desktop', async () => {
const { phone, desktop } = bootstrap;
const window = await app.getWindow();
@ -130,7 +130,7 @@ describe('editing', function needsName() {
assert.strictEqual(await messages.count(), 1, 'message count');
});
it('handles incoming edited messages contact -> desktop', async () => {
it('handles incoming edited messages contact to desktop', async () => {
const { contacts, desktop } = bootstrap;
const window = await app.getWindow();

View file

@ -31,8 +31,6 @@ type MessageWithAvatar<Message extends OptionalFields> = Omit<
expireTimer?: DurationInSeconds;
};
export type ModifiedGroupDetails = MessageWithAvatar<Proto.GroupDetails>;
export type ModifiedContactDetails = MessageWithAvatar<Proto.ContactDetails>;
/* eslint-disable @typescript-eslint/brace-style -- Prettier conflicts with ESLint */
@ -107,41 +105,6 @@ abstract class ParserBase<
}
}
export class GroupBuffer extends ParserBase<
Proto.GroupDetails,
typeof Proto.GroupDetails,
ModifiedGroupDetails
> {
constructor(arrayBuffer: Uint8Array) {
super(arrayBuffer, Proto.GroupDetails);
}
public override next(): ModifiedGroupDetails | undefined {
const proto = this.decodeDelimited();
if (!proto) {
return undefined;
}
if (!proto.members) {
return proto;
}
return {
...proto,
members: proto.members.map((member, i) => {
if (!member.uuid) {
return member;
}
return {
...member,
uuid: normalizeUuid(member.uuid, `GroupBuffer.member[${i}].uuid`),
};
}),
};
}
}
export class ContactBuffer extends ParserBase<
Proto.ContactDetails,
typeof Proto.ContactDetails,

View file

@ -72,7 +72,7 @@ import type { EventHandler } from './EventTarget';
import EventTarget from './EventTarget';
import { downloadAttachment } from './downloadAttachment';
import type { IncomingWebSocketRequest } from './WebsocketResources';
import { ContactBuffer, GroupBuffer } from './ContactsParser';
import { ContactBuffer } from './ContactsParser';
import type { WebAPIType } from './WebAPI';
import type { Storage } from './Storage';
import { WarnOnlyError } from './Errors';
@ -112,8 +112,6 @@ import {
ReadSyncEvent,
ViewSyncEvent,
ContactSyncEvent,
GroupEvent,
GroupSyncEvent,
StoryRecipientUpdateEvent,
CallEventSyncEvent,
} from './messageReceiverEvents';
@ -622,16 +620,6 @@ export default class MessageReceiver
handler: (ev: ContactSyncEvent) => void
): void;
public override addEventListener(
name: 'group',
handler: (ev: GroupEvent) => void
): void;
public override addEventListener(
name: 'groupSync',
handler: (ev: GroupSyncEvent) => void
): void;
public override addEventListener(
name: 'envelopeQueued',
handler: (ev: EnvelopeQueuedEvent) => void
@ -2998,10 +2986,6 @@ export default class MessageReceiver
// before moving on since it updates conversation state.
return this.handleContacts(envelope, syncMessage.contacts);
}
if (syncMessage.groups) {
void this.handleGroups(envelope, syncMessage.groups);
return;
}
if (syncMessage.blocked) {
return this.handleBlocked(envelope, syncMessage.blocked);
}
@ -3454,63 +3438,6 @@ export default class MessageReceiver
log.info('handleContacts: finished');
}
private async handleGroups(
envelope: ProcessedEnvelope,
groups: Proto.SyncMessage.IGroups
): Promise<void> {
const logId = getEnvelopeId(envelope);
log.info('group sync');
log.info(`MessageReceiver: handleGroups ${logId}`);
const { blob } = groups;
this.removeFromCache(envelope);
logUnexpectedUrgentValue(envelope, 'groupSync');
if (!blob) {
throw new Error('MessageReceiver.handleGroups: blob field was missing');
}
// Note: we do not return here because we don't want to block the next message on
// this attachment download and a lot of processing of that attachment.
const attachmentPointer = await this.handleAttachment(blob, {
disableRetries: true,
timeout: 90 * SECOND,
});
const groupBuffer = new GroupBuffer(attachmentPointer.data);
let groupDetails = groupBuffer.next();
const promises = [];
while (groupDetails) {
const { id } = groupDetails;
strictAssert(id, 'Group details without id');
if (id.byteLength !== 16) {
log.error(
`onGroupReceived: Id was ${id} bytes, expected 16 bytes. Dropping group.`
);
continue;
}
const ev = new GroupEvent(
{
...groupDetails,
id: Bytes.toBinary(id),
},
envelope.receivedAtCounter
);
const promise = this.dispatchAndWait(logId, ev).catch(e => {
log.error('error processing group', e);
});
groupDetails = groupBuffer.next();
promises.push(promise);
}
await Promise.all(promises);
const ev = new GroupSyncEvent();
return this.dispatchAndWait(logId, ev);
}
private async handleBlocked(
envelope: ProcessedEnvelope,
blocked: Proto.SyncMessage.IBlocked

View file

@ -1367,30 +1367,6 @@ export default class MessageSender {
};
}
static getRequestGroupSyncMessage(): SingleProtoJobData {
const myUuid = window.textsecure.storage.user.getCheckedUuid();
const request = new Proto.SyncMessage.Request();
request.type = Proto.SyncMessage.Request.Type.GROUPS;
const syncMessage = this.createSyncMessage();
syncMessage.request = request;
const contentMessage = new Proto.Content();
contentMessage.syncMessage = syncMessage;
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
return {
contentHint: ContentHint.RESENDABLE,
identifier: myUuid.toString(),
isSyncMessage: true,
protoBase64: Bytes.toBase64(
Proto.Content.encode(contentMessage).finish()
),
type: 'groupSyncRequest',
urgent: false,
};
}
static getRequestContactSyncMessage(): SingleProtoJobData {
const myUuid = window.textsecure.storage.user.getCheckedUuid();

View file

@ -7,7 +7,7 @@
import type { EventHandler } from './EventTarget';
import EventTarget from './EventTarget';
import MessageReceiver from './MessageReceiver';
import type { ContactSyncEvent, GroupSyncEvent } from './messageReceiverEvents';
import type { ContactSyncEvent } from './messageReceiverEvents';
import MessageSender from './SendMessage';
import { assertDev } from '../util/assert';
import * as log from '../logging/log';
@ -19,14 +19,10 @@ class SyncRequestInner extends EventTarget {
contactSync?: boolean;
groupSync?: boolean;
timeout: any;
oncontact: (event: ContactSyncEvent) => void;
ongroup: (event: GroupSyncEvent) => void;
timeoutMillis: number;
constructor(private receiver: MessageReceiver, timeoutMillis?: number) {
@ -41,9 +37,6 @@ class SyncRequestInner extends EventTarget {
this.oncontact = this.onContactSyncComplete.bind(this);
receiver.addEventListener('contactSync', this.oncontact);
this.ongroup = this.onGroupSyncComplete.bind(this);
receiver.addEventListener('groupSync', this.ongroup);
this.timeoutMillis = timeoutMillis || 60000;
}
@ -72,7 +65,6 @@ class SyncRequestInner extends EventTarget {
),
singleProtoJobQueue.add(MessageSender.getRequestBlockSyncMessage()),
singleProtoJobQueue.add(MessageSender.getRequestContactSyncMessage()),
singleProtoJobQueue.add(MessageSender.getRequestGroupSyncMessage()),
]);
} catch (error: unknown) {
log.error(
@ -89,20 +81,15 @@ class SyncRequestInner extends EventTarget {
this.update();
}
onGroupSyncComplete() {
this.groupSync = true;
this.update();
}
update() {
if (this.contactSync && this.groupSync) {
if (this.contactSync) {
this.dispatchEvent(new Event('success'));
this.cleanup();
}
}
onTimeout() {
if (this.contactSync || this.groupSync) {
if (this.contactSync) {
this.dispatchEvent(new Event('success'));
} else {
this.dispatchEvent(new Event('timeout'));
@ -113,7 +100,6 @@ class SyncRequestInner extends EventTarget {
cleanup() {
clearTimeout(this.timeout);
this.receiver.removeEventListener('contactsync', this.oncontact);
this.receiver.removeEventListener('groupSync', this.ongroup);
delete this.listeners;
}
}

View file

@ -5,7 +5,7 @@ import EventTarget from './EventTarget';
import AccountManager from './AccountManager';
import MessageReceiver from './MessageReceiver';
import utils from './Helpers';
import { ContactBuffer, GroupBuffer } from './ContactsParser';
import { ContactBuffer } from './ContactsParser';
import SyncRequest from './SyncRequest';
import MessageSender from './SendMessage';
import { Storage } from './Storage';
@ -19,7 +19,6 @@ export type TextSecureType = {
AccountManager: typeof AccountManager;
ContactBuffer: typeof ContactBuffer;
EventTarget: typeof EventTarget;
GroupBuffer: typeof GroupBuffer;
MessageReceiver: typeof MessageReceiver;
MessageSender: typeof MessageSender;
SyncRequest: typeof SyncRequest;
@ -37,7 +36,6 @@ export const textsecure: TextSecureType = {
AccountManager,
ContactBuffer,
EventTarget,
GroupBuffer,
MessageReceiver,
MessageSender,
SyncRequest,

View file

@ -11,10 +11,7 @@ import type {
ProcessedDataMessage,
ProcessedSent,
} from './Types.d';
import type {
ModifiedContactDetails,
ModifiedGroupDetails,
} from './ContactsParser';
import type { ModifiedContactDetails } from './ContactsParser';
export class EmptyEvent extends Event {
constructor() {
@ -84,26 +81,6 @@ export class ContactSyncEvent extends Event {
}
}
export type GroupEventData = Omit<ModifiedGroupDetails, 'id'> &
Readonly<{
id: string;
}>;
export class GroupEvent extends Event {
constructor(
public readonly groupDetails: GroupEventData,
public readonly receivedAtCounter: number
) {
super('group');
}
}
export class GroupSyncEvent extends Event {
constructor() {
super('groupSync');
}
}
// Emitted right before we do full decrypt on a message, but after Sealed Sender unseal
export class EnvelopeUnsealedEvent extends Event {
constructor(public readonly envelope: ProcessedEnvelope) {

View file

@ -43,7 +43,6 @@ export const sendTypesEnum = z.enum([
'blockSyncRequest',
'configurationSyncRequest',
'contactSyncRequest', // urgent because it blocks the link process
'groupSyncRequest',
'keySyncRequest', // urgent because it blocks the link process
'pniIdentitySyncRequest', // urgent because we need our PNI to be fully functional
@ -51,7 +50,6 @@ export const sendTypesEnum = z.enum([
'blockSync',
'configurationSync',
'contactSync',
'groupSync',
'keySync',
'pniIdentitySync',

View file

@ -2284,10 +2284,10 @@
node-gyp-build "^4.2.3"
uuid "^8.3.0"
"@signalapp/mock-server@3.2.1":
version "3.2.1"
resolved "https://registry.yarnpkg.com/@signalapp/mock-server/-/mock-server-3.2.1.tgz#36fd3e72b44dbcb6c82fdb27bbf56f8393e8f065"
integrity sha512-irT4U3e8Lve9HODGIlXx+vElONaPNe7Ks9QRoSPSR4o0DbUX/g+zUxfEu7gjEi0CQI8OKxcJHe7e5DbE8mvXng==
"@signalapp/mock-server@3.2.3":
version "3.2.3"
resolved "https://registry.yarnpkg.com/@signalapp/mock-server/-/mock-server-3.2.3.tgz#86cebfb1d5e8054f88acc0dcb05c7e18a600dea1"
integrity sha512-JTrrYbYZLyTva/9RPsP18QXYge2Rog9uw7vCEADmTpZbJ4jO3HRw6+viuCKiExpa+Kooe1LgbFfyH3n5iTxRQg==
dependencies:
"@signalapp/libsignal-client" "^0.29.0"
debug "^4.3.2"