Remove sealed sender proto file in favor of libsignal types

This commit is contained in:
Jordan Rose 2025-08-29 14:07:28 -07:00 committed by GitHub
commit a0633efece
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
21 changed files with 132 additions and 230 deletions

View file

@ -1,70 +0,0 @@
// Copyright 2018 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
package signalservice;
option java_package = "org.whispersystems.libsignal.protocol";
option java_outer_classname = "WhisperProtos";
message ServerCertificate {
message Certificate {
optional uint32 id = 1;
optional bytes key = 2;
}
optional bytes certificate = 1;
optional bytes signature = 2;
}
message SenderCertificate {
message Certificate {
optional string senderE164 = 1;
optional string senderUuid = 6;
optional uint32 senderDevice = 2;
optional fixed64 expires = 3;
optional bytes identityKey = 4;
optional ServerCertificate signer = 5;
}
optional bytes certificate = 1;
optional bytes signature = 2;
}
message UnidentifiedSenderMessage {
message Message {
enum Type {
// Our parser does not handle reserved in enums: DESKTOP-1569
// reserved 1;
MESSAGE = 2;
PREKEY_MESSAGE = 3;
// Further cases should line up with Envelope.Type, even though old cases don't.
// reserved 3 to 6;
SENDERKEY_MESSAGE = 7;
PLAINTEXT_CONTENT = 8;
}
enum ContentHint {
// Show an error immediately; it was important but we can't retry.
DEFAULT = 0;
// Sender will try to resend; delay any error UI if possible
RESENDABLE = 1;
// Don't show any error UI at all; this is something sent implicitly like a typing message or a receipt
IMPLICIT = 2;
}
optional Type type = 1;
optional SenderCertificate senderCertificate = 2;
optional bytes content = 3;
optional ContentHint contentHint = 4;
optional bytes groupId = 5;
}
optional bytes ephemeralPublic = 1;
optional bytes encryptedStatic = 2;
optional bytes encryptedMessage = 3;
}

View file

@ -1,6 +1,8 @@
// Copyright 2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { ContentHint } from '@signalapp/libsignal-client';
import { handleMessageSend } from '../../util/handleMessageSend';
import { getSendOptions } from '../../util/getSendOptions';
import {
@ -92,13 +94,11 @@ export async function sendCallingMessage(
const callMessage = Proto.CallMessage.decode(Bytes.fromBase64(protoBase64));
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
try {
if (isGroup(conversation.attributes)) {
await handleMessageSend(
sendContentMessageToGroup({
contentHint: ContentHint.DEFAULT,
contentHint: ContentHint.Default,
contentMessage: new Proto.Content({ callMessage }),
isPartialSend,
messageId: undefined,

View file

@ -1,6 +1,7 @@
// Copyright 2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { ContentHint } from '@signalapp/libsignal-client';
import { isNumber } from 'lodash';
import * as Errors from '../../types/errors';
@ -82,8 +83,7 @@ export async function sendDeleteForEveryone(
}
const sendType = 'deleteForEveryone';
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
const contentHint = ContentHint.RESENDABLE;
const contentHint = ContentHint.Resendable;
const messageIds = [messageId];
const deletedForEveryoneSendStatus = message.get(

View file

@ -1,10 +1,11 @@
// Copyright 2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { ContentHint } from '@signalapp/libsignal-client';
import * as Errors from '../../types/errors';
import { getSendOptions } from '../../util/getSendOptions';
import { isDirectConversation, isMe } from '../../util/whatTypeOfConversation';
import { SignalService as Proto } from '../../protobuf';
import {
handleMultipleSendErrors,
maybeExpandErrors,
@ -68,8 +69,7 @@ export async function sendDeleteStoryForEveryone(
strictAssert(isStory(message.attributes), 'Story message must be a story');
const sendType = 'deleteForEveryone';
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
const contentHint = ContentHint.RESENDABLE;
const contentHint = ContentHint.Resendable;
const deletedForEveryoneSendStatus = message.get(
'deletedForEveryoneSendStatus'

View file

@ -1,6 +1,8 @@
// Copyright 2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { ContentHint } from '@signalapp/libsignal-client';
import { getSendOptions } from '../../util/getSendOptions';
import { isDirectConversation, isMe } from '../../util/whatTypeOfConversation';
import { SignalService as Proto } from '../../protobuf';
@ -70,8 +72,7 @@ export async function sendDirectExpirationTimerUpdate(
profileKey = await ourProfileKeyService.get();
}
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
const contentHint = ContentHint.RESENDABLE;
const contentHint = ContentHint.Resendable;
const sendType = 'expirationTimerUpdate';
const flags = Proto.DataMessage.Flags.EXPIRATION_TIMER_UPDATE;

View file

@ -1,9 +1,10 @@
// Copyright 2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { ContentHint } from '@signalapp/libsignal-client';
import { getSendOptions } from '../../util/getSendOptions';
import { isGroup } from '../../util/whatTypeOfConversation';
import { SignalService as Proto } from '../../protobuf';
import {
handleMultipleSendErrors,
maybeExpandErrors,
@ -66,7 +67,6 @@ export async function sendGroupCallUpdate(
}
const sendType = 'callingMessage';
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
const groupV2 = conversation.getGroupV2Info();
const sendOptions = await getSendOptions(conversation.attributes);
if (!groupV2) {
@ -82,7 +82,7 @@ export async function sendGroupCallUpdate(
send: () =>
conversation.queueJob(logId, () =>
sendToGroup({
contentHint: ContentHint.DEFAULT,
contentHint: ContentHint.Default,
groupSendOptions: {
groupCallUpdate: { eraId },
groupV2,

View file

@ -1,9 +1,10 @@
// Copyright 2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { ContentHint } from '@signalapp/libsignal-client';
import { getSendOptionsForRecipients } from '../../util/getSendOptions';
import { isGroupV2 } from '../../util/whatTypeOfConversation';
import { SignalService as Proto } from '../../protobuf';
import {
handleMultipleSendErrors,
maybeExpandErrors,
@ -70,8 +71,7 @@ export async function sendGroupUpdate(
const sendOptions = await getSendOptionsForRecipients(recipients);
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
const contentHint = ContentHint.RESENDABLE;
const contentHint = ContentHint.Resendable;
const sendType = 'groupChange';
const groupChange = groupChangeBase64

View file

@ -3,6 +3,7 @@
import { isNumber } from 'lodash';
import PQueue from 'p-queue';
import { ContentHint } from '@signalapp/libsignal-client';
import * as Errors from '../../types/errors';
import { strictAssert } from '../../util/assert';
@ -11,7 +12,6 @@ import { getMessageById } from '../../messages/getMessageById';
import type { ConversationModel } from '../../models/conversations';
import { isGroup, isGroupV2, isMe } from '../../util/whatTypeOfConversation';
import { getSendOptions } from '../../util/getSendOptions';
import { SignalService as Proto } from '../../protobuf';
import { handleMessageSend } from '../../util/handleMessageSend';
import { findAndFormatContact } from '../../util/findAndFormatContact';
import { uploadAttachment } from '../../util/uploadAttachment';
@ -302,7 +302,6 @@ export async function sendNormalMessage(
} else {
const conversationType = conversation.get('type');
const sendOptions = await getSendOptions(conversation.attributes);
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
let innerPromise: Promise<CallbackResultType>;
if (conversationType === Message.GROUP) {
@ -324,7 +323,7 @@ export async function sendNormalMessage(
abortSignal =>
sendToGroup({
abortSignal,
contentHint: ContentHint.RESENDABLE,
contentHint: ContentHint.Resendable,
groupSendOptions: {
attachments,
bodyRanges,
@ -392,7 +391,7 @@ export async function sendNormalMessage(
attachments,
bodyRanges,
contact,
contentHint: ContentHint.RESENDABLE,
contentHint: ContentHint.Resendable,
deletedForEveryoneTimestamp,
expireTimer,
expireTimerVersion: conversation.getExpireTimerVersion(),

View file

@ -1,10 +1,11 @@
// Copyright 2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { ContentHint } from '@signalapp/libsignal-client';
import { handleMessageSend } from '../../util/handleMessageSend';
import { getSendOptions } from '../../util/getSendOptions';
import { isDirectConversation } from '../../util/whatTypeOfConversation';
import { SignalService as Proto } from '../../protobuf';
import {
handleMultipleSendErrors,
maybeExpandErrors,
@ -62,8 +63,7 @@ export async function sendNullMessage(
);
const sendOptions = await getSendOptions(conversation.attributes);
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
const contentHint = ContentHint.RESENDABLE;
const contentHint = ContentHint.Resendable;
const sendType = 'nullMessage';
// Note: we will send to blocked users, to those still in message request state, etc.
@ -109,7 +109,7 @@ export async function sendNullMessage(
abortSignal =>
sendToGroup({
abortSignal,
contentHint: ContentHint.RESENDABLE,
contentHint: ContentHint.Resendable,
groupSendOptions: {
attachments: [],
bodyRanges: [],

View file

@ -2,6 +2,7 @@
// SPDX-License-Identifier: AGPL-3.0-only
import { isNumber } from 'lodash';
import { ContentHint } from '@signalapp/libsignal-client';
import { handleMessageSend } from '../../util/handleMessageSend';
import { getSendOptions } from '../../util/getSendOptions';
@ -95,8 +96,7 @@ export async function sendProfileKey(
const { revision } = data;
const sendOptions = await getSendOptions(conversation.attributes);
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
const contentHint = ContentHint.RESENDABLE;
const contentHint = ContentHint.Resendable;
const sendType = 'profileKeyUpdate';
let sendPromise: Promise<CallbackResultType>;

View file

@ -2,6 +2,7 @@
// SPDX-License-Identifier: AGPL-3.0-only
import { isNumber } from 'lodash';
import { ContentHint } from '@signalapp/libsignal-client';
import * as Errors from '../../types/errors';
import { strictAssert } from '../../util/assert';
@ -21,7 +22,6 @@ import {
isGroupV2,
} from '../../util/whatTypeOfConversation';
import { getSendOptions } from '../../util/getSendOptions';
import { SignalService as Proto } from '../../protobuf';
import { handleMessageSend } from '../../util/handleMessageSend';
import { ourProfileKeyService } from '../../services/ourProfileKey';
import { canReact, isStory } from '../../state/selectors/message';
@ -211,7 +211,6 @@ export async function sendReaction(
successfulConversationIds.add(ourConversationId);
} else {
const sendOptions = await getSendOptions(conversation.attributes);
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
let promise: Promise<CallbackResultType>;
if (isDirectConversation(conversation.attributes)) {
@ -250,7 +249,7 @@ export async function sendReaction(
timestamp: pendingReaction.timestamp,
expireTimer,
expireTimerVersion: conversation.getExpireTimerVersion(),
contentHint: ContentHint.RESENDABLE,
contentHint: ContentHint.Resendable,
groupId: undefined,
profileKey,
options: sendOptions,
@ -276,7 +275,7 @@ export async function sendReaction(
return sendToGroup({
abortSignal,
contentHint: ContentHint.RESENDABLE,
contentHint: ContentHint.Resendable,
groupSendOptions: {
groupV2: groupV2Info,
reaction: reactionForSend,

View file

@ -1,12 +1,11 @@
// Copyright 2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { PlaintextContent } from '@signalapp/libsignal-client';
import { ContentHint, PlaintextContent } from '@signalapp/libsignal-client';
import { handleMessageSend } from '../../util/handleMessageSend';
import { getSendOptions } from '../../util/getSendOptions';
import { isDirectConversation } from '../../util/whatTypeOfConversation';
import { SignalService as Proto } from '../../protobuf';
import {
handleMultipleSendErrors,
maybeExpandErrors,
@ -98,7 +97,6 @@ export async function sendResendRequest(
const plaintext = PlaintextContent.deserialize(
Bytes.fromBase64(plaintextBase64)
);
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
// We run this job on the queue for the individual sender we want the resend from, but
// the original message might have been sent in a group - and that's where we'll put
@ -113,7 +111,7 @@ export async function sendResendRequest(
timestamp,
recipients: [senderAci],
proto: plaintext,
contentHint: ContentHint.DEFAULT,
contentHint: ContentHint.Default,
groupId,
options,
urgent: false,
@ -124,7 +122,7 @@ export async function sendResendRequest(
// Now that we've successfully sent, represent this to the user. Three options:
// 1. We believe that it could be successfully re-sent, so we'll add a placeholder.
if (contentHint === ContentHint.RESENDABLE) {
if (contentHint === ContentHint.Resendable) {
const { retryPlaceholders } = window.Signal.Services;
strictAssert(retryPlaceholders, 'sendResendRequest: adding placeholder');
@ -148,7 +146,7 @@ export async function sendResendRequest(
// 2. This message cannot be resent. We'll show no error and trust the other side to
// reset their session.
if (contentHint === ContentHint.IMPLICIT) {
if (contentHint === ContentHint.Implicit) {
log.info('contentHint is IMPLICIT, adding no timeline item.');
return;
}

View file

@ -2,6 +2,8 @@
// SPDX-License-Identifier: AGPL-3.0-only
import { isEqual } from 'lodash';
import { ContentHint } from '@signalapp/libsignal-client';
import type { UploadedAttachmentType } from '../../types/Attachment';
import type { ConversationModel } from '../../models/conversations';
import type {
@ -324,8 +326,6 @@ export async function sendStory(
return;
}
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
const sendOptions = await getSendOptionsForRecipients(
pendingSendRecipientServiceIds,
{ story: true }
@ -356,7 +356,7 @@ export async function sendStory(
contentMessage.storyMessage = storyMessage;
const innerPromise = sendContentMessageToGroup({
contentHint: ContentHint.IMPLICIT,
contentHint: ContentHint.Implicit,
contentMessage,
isPartialSend: false,
messageId: undefined,

View file

@ -4,6 +4,7 @@
import { compact, isNumber, throttle, debounce } from 'lodash';
import { v4 as generateGuid } from 'uuid';
import PQueue from 'p-queue';
import { ContentHint } from '@signalapp/libsignal-client';
import type { ReadonlyDeep } from 'type-fest';
import type {
@ -1377,8 +1378,6 @@ export class ConversationModel {
const contentMessage = messaging.getTypingContentMessage(content);
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
const sendOptions = {
...(await getSendOptions(this.attributes)),
online: true,
@ -1386,7 +1385,7 @@ export class ConversationModel {
if (isDirectConversation(this.attributes)) {
await handleMessageSend(
messaging.sendMessageProtoAndWait({
contentHint: ContentHint.IMPLICIT,
contentHint: ContentHint.Implicit,
groupId: undefined,
options: sendOptions,
proto: contentMessage,
@ -1399,7 +1398,7 @@ export class ConversationModel {
} else {
await handleMessageSend(
sendContentMessageToGroup({
contentHint: ContentHint.IMPLICIT,
contentHint: ContentHint.Implicit,
contentMessage,
messageId: undefined,
online: true,

View file

@ -1,6 +1,8 @@
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { SenderCertificate } from '@signalapp/libsignal-client';
import type { SerializedCertificateType } from '../textsecure/OutgoingMessage';
import {
SenderCertificateMode,
@ -14,9 +16,6 @@ import { createLogger } from '../logging/log';
import type { StorageInterface } from '../types/Storage.d';
import * as Errors from '../types/errors';
import type { WebAPIType } from '../textsecure/WebAPI';
import { SignalService as Proto } from '../protobuf';
import SenderCertificate = Proto.SenderCertificate;
import { safeParseUnknown } from '../util/schemas';
const log = createLogger('senderCertificate');
@ -176,11 +175,8 @@ export class SenderCertificateService {
return undefined;
}
const certificate = Bytes.fromBase64(certificateString);
const decodedContainer = SenderCertificate.decode(certificate);
const decodedCert = decodedContainer.certificate
? SenderCertificate.Certificate.decode(decodedContainer.certificate)
: undefined;
const expires = decodedCert?.expires?.toNumber();
const decodedCert = SenderCertificate.deserialize(certificate);
const expires = decodedCert.expiration();
if (!isExpirationValid(expires)) {
log.warn(
@ -240,8 +236,8 @@ function modeToLogString(mode: SenderCertificateMode): string {
}
}
function isExpirationValid(expiration: unknown): expiration is number {
return typeof expiration === 'number' && expiration > Date.now();
function isExpirationValid(expiration: number): boolean {
return expiration > Date.now();
}
export const senderCertificateService = new SenderCertificateService();

View file

@ -6,18 +6,20 @@
import { assert } from 'chai';
import * as sinon from 'sinon';
import { v4 as uuid } from 'uuid';
import Long from 'long';
import {
IdentityKeyPair,
SenderCertificate,
ServerCertificate,
} from '@signalapp/libsignal-client';
import * as durations from '../../util/durations';
import { drop } from '../../util/drop';
import * as Bytes from '../../Bytes';
import { SenderCertificateMode } from '../../textsecure/OutgoingMessage';
import { SignalService as Proto } from '../../protobuf';
import { SenderCertificateService } from '../../services/senderCertificate';
import SenderCertificate = Proto.SenderCertificate;
describe('SenderCertificateService', () => {
const FIFTEEN_MINUTES = 15 * durations.MINUTE;
@ -39,14 +41,26 @@ describe('SenderCertificateService', () => {
}
beforeEach(() => {
fakeValidCertificate = new SenderCertificate();
const fakeTrustRoot = IdentityKeyPair.generate();
const fakeServerKey = IdentityKeyPair.generate();
const fakeSenderIdentityKey = IdentityKeyPair.generate();
const fakeServerCert = ServerCertificate.new(
1,
fakeServerKey.publicKey,
fakeTrustRoot.privateKey
);
fakeValidCertificateExpiry = Date.now() + 604800000;
const certificate = new SenderCertificate.Certificate();
certificate.expires = Long.fromNumber(fakeValidCertificateExpiry);
fakeValidCertificate.certificate =
SenderCertificate.Certificate.encode(certificate).finish();
fakeValidEncodedCertificate =
SenderCertificate.encode(fakeValidCertificate).finish();
fakeValidCertificate = SenderCertificate.new(
'aaaaaaaa-7000-11eb-b32a-33b8a8a487a6',
null,
2,
fakeSenderIdentityKey.publicKey,
fakeValidCertificateExpiry,
fakeServerCert,
fakeServerKey.privateKey
);
fakeValidEncodedCertificate = fakeValidCertificate.serialize();
fakeServer = {
isOnline: () => true,
@ -65,7 +79,9 @@ describe('SenderCertificateService', () => {
put: sinon.stub().resolves(),
remove: sinon.stub().resolves(),
};
fakeStorage.get.withArgs('uuid_id').returns(`${uuid()}.2`);
fakeStorage.get
.withArgs('uuid_id')
.returns('aaaaaaaa-7000-11eb-b32a-33b8a8a487a6.2');
fakeStorage.get.withArgs('password').returns('abc123');
});
@ -199,15 +215,28 @@ describe('SenderCertificateService', () => {
it('returns undefined if the server returns an already-expired certificate', async () => {
const service = initializeTestService();
const expiredCertificate = new SenderCertificate();
const certificate = new SenderCertificate.Certificate();
certificate.expires = Long.fromNumber(Date.now() - 1000);
expiredCertificate.certificate =
SenderCertificate.Certificate.encode(certificate).finish();
const fakeTrustRoot = IdentityKeyPair.generate();
const fakeServerKey = IdentityKeyPair.generate();
const fakeSenderIdentityKey = IdentityKeyPair.generate();
const fakeServerCert = ServerCertificate.new(
1,
fakeServerKey.publicKey,
fakeTrustRoot.privateKey
);
const expiry = Date.now() - 1000;
const expiredCertificate = SenderCertificate.new(
'aaaaaaaa-7000-11eb-b32a-33b8a8a487a6',
null,
1,
fakeSenderIdentityKey.publicKey,
expiry,
fakeServerCert,
fakeServerKey.privateKey
);
fakeServer.getSenderCertificate.resolves({
certificate: Bytes.toBase64(
SenderCertificate.encode(expiredCertificate).finish()
),
certificate: Bytes.toBase64(expiredCertificate.serialize()),
});
assert.isUndefined(await service.get(SenderCertificateMode.WithE164));

View file

@ -1699,12 +1699,7 @@ export default class MessageReceiver
'Missing sender certificate for sealed sender message'
);
const unidentifiedSenderTypeEnum =
Proto.UnidentifiedSenderMessage.Message.Type;
if (
messageContent.msgType() === unidentifiedSenderTypeEnum.PLAINTEXT_CONTENT
) {
if (messageContent.msgType() === CiphertextMessageType.Plaintext) {
log.info(
`decryptSealedSender(${logId}): ` +
'unidentified message/plaintext contents'
@ -1719,9 +1714,7 @@ export default class MessageReceiver
};
}
if (
messageContent.msgType() === unidentifiedSenderTypeEnum.SENDERKEY_MESSAGE
) {
if (messageContent.msgType() === CiphertextMessageType.SenderKey) {
log.info(
`decryptSealedSender(${logId}): ` +
'unidentified message/sender key contents'
@ -1777,7 +1770,7 @@ export default class MessageReceiver
envelope.sourceDevice
);
const message =
messageContent.msgType() === unidentifiedSenderTypeEnum.PREKEY_MESSAGE
messageContent.msgType() === CiphertextMessageType.PreKey
? PreKeySignalMessage.deserialize(messageContent.contents())
: SignalMessage.deserialize(messageContent.contents());
const plaintext = await this.#storage.protocol.enqueueSessionJob(

View file

@ -10,6 +10,7 @@ import PQueue from 'p-queue';
import pMap from 'p-map';
import type { PlaintextContent } from '@signalapp/libsignal-client';
import {
ContentHint,
ProtocolAddress,
SenderKeyDistributionMessage,
} from '@signalapp/libsignal-client';
@ -1381,13 +1382,11 @@ export default class MessageSender {
const contentMessage = new Proto.Content();
contentMessage.syncMessage = syncMessage;
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
return this.sendIndividualProto({
serviceId: myAci,
proto: contentMessage,
timestamp,
contentHint: ContentHint.RESENDABLE,
contentHint: ContentHint.Resendable,
options,
urgent,
});
@ -1403,10 +1402,8 @@ export default class MessageSender {
const contentMessage = new Proto.Content();
contentMessage.syncMessage = syncMessage;
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
return {
contentHint: ContentHint.RESENDABLE,
contentHint: ContentHint.Resendable,
serviceId: myAci,
isSyncMessage: true,
protoBase64: Bytes.toBase64(
@ -1427,10 +1424,8 @@ export default class MessageSender {
const contentMessage = new Proto.Content();
contentMessage.syncMessage = syncMessage;
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
return {
contentHint: ContentHint.RESENDABLE,
contentHint: ContentHint.Resendable,
serviceId: myAci,
isSyncMessage: true,
protoBase64: Bytes.toBase64(
@ -1451,10 +1446,8 @@ export default class MessageSender {
const contentMessage = new Proto.Content();
contentMessage.syncMessage = syncMessage;
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
return {
contentHint: ContentHint.RESENDABLE,
contentHint: ContentHint.Resendable,
serviceId: myAci,
isSyncMessage: true,
protoBase64: Bytes.toBase64(
@ -1476,10 +1469,8 @@ export default class MessageSender {
const contentMessage = new Proto.Content();
contentMessage.syncMessage = syncMessage;
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
return {
contentHint: ContentHint.RESENDABLE,
contentHint: ContentHint.Resendable,
serviceId: myAci,
isSyncMessage: true,
protoBase64: Bytes.toBase64(
@ -1501,10 +1492,8 @@ export default class MessageSender {
const contentMessage = new Proto.Content();
contentMessage.syncMessage = syncMessage;
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
return {
contentHint: ContentHint.RESENDABLE,
contentHint: ContentHint.Resendable,
serviceId: myAci,
isSyncMessage: true,
protoBase64: Bytes.toBase64(
@ -1526,10 +1515,8 @@ export default class MessageSender {
const contentMessage = new Proto.Content();
contentMessage.syncMessage = syncMessage;
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
return {
contentHint: ContentHint.RESENDABLE,
contentHint: ContentHint.Resendable,
serviceId: myAci,
isSyncMessage: true,
protoBase64: Bytes.toBase64(
@ -1624,10 +1611,8 @@ export default class MessageSender {
const contentMessage = new Proto.Content();
contentMessage.syncMessage = syncMessage;
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
return {
contentHint: ContentHint.RESENDABLE,
contentHint: ContentHint.Resendable,
serviceId: myAci,
isSyncMessage: true,
protoBase64: Bytes.toBase64(
@ -1653,10 +1638,8 @@ export default class MessageSender {
const contentMessage = new Proto.Content();
contentMessage.syncMessage = syncMessage;
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
return {
contentHint: ContentHint.RESENDABLE,
contentHint: ContentHint.Resendable,
serviceId: myAci,
isSyncMessage: true,
protoBase64: Bytes.toBase64(
@ -1684,10 +1667,8 @@ export default class MessageSender {
const contentMessage = new Proto.Content();
contentMessage.syncMessage = syncMessage;
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
return {
contentHint: ContentHint.RESENDABLE,
contentHint: ContentHint.Resendable,
serviceId: ourAci,
isSyncMessage: true,
protoBase64: Bytes.toBase64(
@ -1722,10 +1703,8 @@ export default class MessageSender {
const contentMessage = new Proto.Content();
contentMessage.syncMessage = syncMessage;
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
return {
contentHint: ContentHint.RESENDABLE,
contentHint: ContentHint.Resendable,
serviceId: ourAci,
isSyncMessage: true,
protoBase64: Bytes.toBase64(
@ -1759,13 +1738,11 @@ export default class MessageSender {
const contentMessage = new Proto.Content();
contentMessage.syncMessage = syncMessage;
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
return this.sendIndividualProto({
serviceId: myAci,
proto: contentMessage,
timestamp: Date.now(),
contentHint: ContentHint.RESENDABLE,
contentHint: ContentHint.Resendable,
options,
urgent: true,
});
@ -1792,13 +1769,11 @@ export default class MessageSender {
const contentMessage = new Proto.Content();
contentMessage.syncMessage = syncMessage;
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
return this.sendIndividualProto({
serviceId: myAci,
proto: contentMessage,
timestamp: Date.now(),
contentHint: ContentHint.RESENDABLE,
contentHint: ContentHint.Resendable,
options,
urgent: false,
});
@ -1839,13 +1814,11 @@ export default class MessageSender {
const contentMessage = new Proto.Content();
contentMessage.syncMessage = syncMessage;
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
return this.sendIndividualProto({
serviceId: myAci,
proto: contentMessage,
timestamp: Date.now(),
contentHint: ContentHint.RESENDABLE,
contentHint: ContentHint.Resendable,
options,
urgent: false,
});
@ -1877,10 +1850,8 @@ export default class MessageSender {
const contentMessage = new Proto.Content();
contentMessage.syncMessage = syncMessage;
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
return {
contentHint: ContentHint.RESENDABLE,
contentHint: ContentHint.Resendable,
serviceId: myAci,
isSyncMessage: true,
protoBase64: Bytes.toBase64(
@ -1921,10 +1892,8 @@ export default class MessageSender {
const contentMessage = new Proto.Content();
contentMessage.syncMessage = syncMessage;
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
return {
contentHint: ContentHint.RESENDABLE,
contentHint: ContentHint.Resendable,
serviceId: myAci,
isSyncMessage: true,
protoBase64: Bytes.toBase64(
@ -1962,10 +1931,8 @@ export default class MessageSender {
const contentMessage = new Proto.Content();
contentMessage.syncMessage = syncMessage;
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
return {
contentHint: ContentHint.RESENDABLE,
contentHint: ContentHint.Resendable,
serviceId: myAci,
isSyncMessage: true,
protoBase64: Bytes.toBase64(
@ -2009,10 +1976,8 @@ export default class MessageSender {
const contentMessage = new Proto.Content();
contentMessage.syncMessage = syncMessage;
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
return {
contentHint: ContentHint.RESENDABLE,
contentHint: ContentHint.Resendable,
serviceId: myAci,
isSyncMessage: true,
protoBase64: Bytes.toBase64(
@ -2045,13 +2010,11 @@ export default class MessageSender {
reason: `sendCallingMessage(${timestamp})`,
});
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
return this.sendMessageProtoAndWait({
timestamp,
recipients,
proto: contentMessage,
contentHint: ContentHint.DEFAULT,
contentHint: ContentHint.Default,
groupId: undefined,
options,
urgent,
@ -2134,13 +2097,11 @@ export default class MessageSender {
});
}
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
return this.sendIndividualProto({
serviceId: senderAci,
proto: contentMessage,
timestamp,
contentHint: ContentHint.RESENDABLE,
contentHint: ContentHint.Resendable,
options,
urgent: false,
});
@ -2389,7 +2350,6 @@ export default class MessageSender {
options?: Readonly<SendOptionsType>
): Promise<CallbackResultType> {
const timestamp = Date.now();
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
const contentMessage = await this.getSenderKeyDistributionMessage(
distributionId,
{
@ -2401,7 +2361,7 @@ export default class MessageSender {
const sendLogCallback =
serviceIds.length > 1
? this.makeSendLogCallback({
contentHint: contentHint ?? ContentHint.IMPLICIT,
contentHint: contentHint ?? ContentHint.Implicit,
proto: Proto.Content.encode(contentMessage).finish(),
sendType: 'senderKeyDistributionMessage',
timestamp,
@ -2411,7 +2371,7 @@ export default class MessageSender {
: undefined;
return this.sendGroupProto({
contentHint: contentHint ?? ContentHint.IMPLICIT,
contentHint: contentHint ?? ContentHint.Implicit,
groupId,
options,
proto: contentMessage,

View file

@ -11,6 +11,7 @@ import {
callIdFromRingId,
RingUpdate,
} from '@signalapp/ringrtc';
import { ContentHint } from '@signalapp/libsignal-client';
import { isEqual } from 'lodash';
import { strictAssert } from './assert';
import { DataReader, DataWriter } from '../sql/Client';
@ -1305,10 +1306,8 @@ async function updateRemoteCallHistory(
const contentMessage = new Proto.Content();
contentMessage.syncMessage = syncMessage;
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
await singleProtoJobQueue.add({
contentHint: ContentHint.RESENDABLE,
contentHint: ContentHint.Resendable,
serviceId: ourAci,
isSyncMessage: true,
protoBase64: Bytes.toBase64(
@ -1468,11 +1467,9 @@ export async function markAllCallHistoryReadAndSync(
const contentMessage = new Proto.Content();
contentMessage.syncMessage = syncMessage;
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
log.info('markAllCallHistoryReadAndSync: Queueing sync message');
await singleProtoJobQueue.add({
contentHint: ContentHint.RESENDABLE,
contentHint: ContentHint.Resendable,
serviceId: ourAci,
isSyncMessage: true,
protoBase64: Bytes.toBase64(

View file

@ -1,5 +1,8 @@
// Copyright 2024 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { ContentHint } from '@signalapp/libsignal-client';
import * as Bytes from '../Bytes';
import { CallLinkUpdateSyncType } from '../types/CallLink';
import { createLogger } from '../logging/log';
@ -55,10 +58,8 @@ async function _sendCallLinkUpdateSync(
const contentMessage = new Proto.Content();
contentMessage.syncMessage = syncMessage;
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
await singleProtoJobQueue.add({
contentHint: ContentHint.RESENDABLE,
contentHint: ContentHint.Resendable,
serviceId: ourAci,
isSyncMessage: true,
protoBase64: Bytes.toBase64(

View file

@ -5,6 +5,7 @@ import { differenceWith, omit } from 'lodash';
import { v4 as generateUuid } from 'uuid';
import {
ContentHint,
ErrorCode,
LibSignalErrorBase,
groupEncrypt,
@ -293,7 +294,6 @@ export async function sendToGroupViaSenderKey(
timestamp,
urgent,
} = options;
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
const logId = `sendToGroupViaSenderKey/${sendTarget.idForLogging()}`;
log.info(
@ -312,9 +312,9 @@ export async function sendToGroupViaSenderKey(
}
if (
contentHint !== ContentHint.DEFAULT &&
contentHint !== ContentHint.RESENDABLE &&
contentHint !== ContentHint.IMPLICIT
contentHint !== ContentHint.Default &&
contentHint !== ContentHint.Resendable &&
contentHint !== ContentHint.Implicit
) {
throw new Error(`${logId}: Invalid contentHint ${contentHint}`);
}