From 2eaacac151f85be94aab3e21972ba5c2cfbb0e55 Mon Sep 17 00:00:00 2001 From: Fedor Indutny <79877362+indutny-signal@users.noreply.github.com> Date: Wed, 23 Mar 2022 13:49:27 -0700 Subject: [PATCH] Use --force-long with pbjs --- package.json | 2 +- ts/Crypto.ts | 2 +- ts/groups.ts | 13 ++----- ts/services/senderCertificate.ts | 3 +- ts/services/storage.ts | 16 +++++--- ts/test-both/processDataMessage_test.ts | 12 +++--- ts/test-both/util/normalizeNumber_test.ts | 21 ----------- ts/test-electron/MessageReceiver_test.ts | 5 ++- ts/test-electron/WebsocketResources_test.ts | 2 +- ts/textsecure/MessageReceiver.ts | 32 +++++++--------- ts/textsecure/SendMessage.ts | 41 +++++++++++++++------ ts/textsecure/WebsocketResources.ts | 37 ++++++++++--------- ts/textsecure/processDataMessage.ts | 21 ++++------- ts/util/normalizeNumber.ts | 17 --------- ts/util/timestampLongUtils.ts | 6 +-- 15 files changed, 99 insertions(+), 131 deletions(-) delete mode 100644 ts/test-both/util/normalizeNumber_test.ts delete mode 100644 ts/util/normalizeNumber.ts diff --git a/package.json b/package.json index 1a25af0e9..d78aff670 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "get-expire-time": "node ts/scripts/get-expire-time.js", "copy-and-concat": "node ts/scripts/copy-and-concat.js", "sass": "sass stylesheets/manifest.scss:stylesheets/manifest.css stylesheets/manifest_bridge.scss:stylesheets/manifest_bridge.css", - "build-module-protobuf": "pbjs --target static-module --no-verify --no-create --wrap commonjs --out ts/protobuf/compiled.js protos/*.proto && pbts --out ts/protobuf/compiled.d.ts ts/protobuf/compiled.js", + "build-module-protobuf": "pbjs --target static-module --force-long --no-verify --no-create --wrap commonjs --out ts/protobuf/compiled.js protos/*.proto && pbts --out ts/protobuf/compiled.d.ts ts/protobuf/compiled.js", "clean-module-protobuf": "rm -f ts/protobuf/compiled.d.ts ts/protobuf/compiled.js", "build-protobuf": "yarn build-module-protobuf", "clean-protobuf": "yarn clean-module-protobuf", diff --git a/ts/Crypto.ts b/ts/Crypto.ts index cf116b27b..8d358d691 100644 --- a/ts/Crypto.ts +++ b/ts/Crypto.ts @@ -142,7 +142,7 @@ export function decryptDeviceName( export function deriveStorageManifestKey( storageServiceKey: Uint8Array, - version: number + version: Long = Long.fromNumber(0) ): Uint8Array { return hmacSha256(storageServiceKey, Bytes.fromString(`Manifest_${version}`)); } diff --git a/ts/groups.ts b/ts/groups.ts index daebf8947..b2985eaf2 100644 --- a/ts/groups.ts +++ b/ts/groups.ts @@ -10,6 +10,7 @@ import { last, values, } from 'lodash'; +import Long from 'long'; import type { ClientZkGroupCipher } from '@signalapp/signal-client/zkgroup'; import { v4 as getGuid } from 'uuid'; import LRU from 'lru-cache'; @@ -614,7 +615,7 @@ function buildGroupProto( member.role = item.role || MEMBER_ROLE_ENUM.DEFAULT; pendingMember.member = member; - pendingMember.timestamp = item.timestamp; + pendingMember.timestamp = Long.fromNumber(item.timestamp); pendingMember.addedByUserId = ourUuidCipherTextBuffer; return pendingMember; @@ -717,7 +718,7 @@ export async function buildAddMembersChange( const memberPendingProfileKey = new Proto.MemberPendingProfileKey(); memberPendingProfileKey.member = member; memberPendingProfileKey.addedByUserId = ourUuidCipherTextBuffer; - memberPendingProfileKey.timestamp = now; + memberPendingProfileKey.timestamp = Long.fromNumber(now); const addPendingMemberAction = new Proto.GroupChange.Actions.AddMemberPendingProfileKeyAction(); @@ -5112,17 +5113,11 @@ function isValidProfileKey(buffer?: Uint8Array): boolean { return Boolean(buffer && buffer.length === 32); } -function normalizeTimestamp( - timestamp: number | Long | null | undefined -): number { +function normalizeTimestamp(timestamp: Long | null | undefined): number { if (!timestamp) { return 0; } - if (typeof timestamp === 'number') { - return timestamp; - } - const asNumber = timestamp.toNumber(); const now = Date.now(); diff --git a/ts/services/senderCertificate.ts b/ts/services/senderCertificate.ts index c0c625b61..446854322 100644 --- a/ts/services/senderCertificate.ts +++ b/ts/services/senderCertificate.ts @@ -9,7 +9,6 @@ import { import * as Bytes from '../Bytes'; import { assert } from '../util/assert'; import { missingCaseError } from '../util/missingCaseError'; -import { normalizeNumber } from '../util/normalizeNumber'; import { waitForOnline } from '../util/waitForOnline'; import * as log from '../logging/log'; import type { StorageInterface } from '../types/Storage.d'; @@ -181,7 +180,7 @@ export class SenderCertificateService { const decodedCert = decodedContainer.certificate ? SenderCertificate.Certificate.decode(decodedContainer.certificate) : undefined; - const expires = normalizeNumber(decodedCert?.expires); + const expires = decodedCert?.expires?.toNumber(); if (!isExpirationValid(expires)) { log.warn( diff --git a/ts/services/storage.ts b/ts/services/storage.ts index 5f20b2522..a9281ce04 100644 --- a/ts/services/storage.ts +++ b/ts/services/storage.ts @@ -3,6 +3,7 @@ import { debounce, isNumber } from 'lodash'; import pMap from 'p-map'; +import Long from 'long'; import dataInterface from '../sql/Client'; import * as Bytes from '../Bytes'; @@ -27,12 +28,12 @@ import { import type { MergeResultType } from './storageRecordOps'; import type { ConversationModel } from '../models/conversations'; import { strictAssert } from '../util/assert'; +import { dropNull } from '../util/dropNull'; import * as durations from '../util/durations'; import { BackOff } from '../util/BackOff'; import { storageJobQueue } from '../util/JobQueue'; import { sleep } from '../util/sleep'; import { isMoreRecentThan } from '../util/timestamp'; -import { normalizeNumber } from '../util/normalizeNumber'; import { ourProfileKeyService } from './ourProfileKey'; import { ConversationTypes, @@ -495,7 +496,7 @@ async function generateManifest( } const manifestRecord = new Proto.ManifestRecord(); - manifestRecord.version = version; + manifestRecord.version = Long.fromNumber(version); manifestRecord.keys = Array.from(manifestRecordKeys); const storageKeyBase64 = window.storage.get('storageKey'); @@ -503,14 +504,17 @@ async function generateManifest( throw new Error('No storage key'); } const storageKey = Bytes.fromBase64(storageKeyBase64); - const storageManifestKey = deriveStorageManifestKey(storageKey, version); + const storageManifestKey = deriveStorageManifestKey( + storageKey, + Long.fromNumber(version) + ); const encryptedManifest = encryptProfile( Proto.ManifestRecord.encode(manifestRecord).finish(), storageManifestKey ); const storageManifest = new Proto.StorageManifest(); - storageManifest.version = version; + storageManifest.version = manifestRecord.version; storageManifest.value = encryptedManifest; return { @@ -676,7 +680,7 @@ async function decryptManifest( const storageKey = Bytes.fromBase64(storageKeyBase64); const storageManifestKey = deriveStorageManifestKey( storageKey, - normalizeNumber(version ?? 0) + dropNull(version) ); strictAssert(value, 'StorageManifest has no value field'); @@ -1317,7 +1321,7 @@ async function sync( manifest.version !== undefined && manifest.version !== null, 'Manifest without version' ); - const version = normalizeNumber(manifest.version); + const version = manifest.version?.toNumber() ?? 0; log.info( `storageService.sync: updating to remoteVersion=${version} from ` + diff --git a/ts/test-both/processDataMessage_test.ts b/ts/test-both/processDataMessage_test.ts index ae1bf214e..ba2599cf3 100644 --- a/ts/test-both/processDataMessage_test.ts +++ b/ts/test-both/processDataMessage_test.ts @@ -16,7 +16,7 @@ const FLAGS = Proto.DataMessage.Flags; const TIMESTAMP = Date.now(); const UNPROCESSED_ATTACHMENT: Proto.IAttachmentPointer = { - cdnId: 123, + cdnId: Long.fromNumber(123), key: new Uint8Array([1, 2, 3]), digest: new Uint8Array([4, 5, 6]), }; @@ -35,7 +35,7 @@ describe('processDataMessage', () => { const check = (message: Proto.IDataMessage) => processDataMessage( { - timestamp: TIMESTAMP, + timestamp: Long.fromNumber(TIMESTAMP), ...message, }, TIMESTAMP @@ -175,7 +175,7 @@ describe('processDataMessage', () => { it('should process quote', async () => { const out = await check({ quote: { - id: 1, + id: Long.fromNumber(1), authorUuid: 'author', text: 'text', attachments: [ @@ -236,7 +236,7 @@ describe('processDataMessage', () => { await check({ reaction: { emoji: '😎', - targetTimestamp: TIMESTAMP, + targetTimestamp: Long.fromNumber(TIMESTAMP), }, }) ).reaction, @@ -254,7 +254,7 @@ describe('processDataMessage', () => { reaction: { emoji: '😎', remove: true, - targetTimestamp: TIMESTAMP, + targetTimestamp: Long.fromNumber(TIMESTAMP), }, }) ).reaction, @@ -271,7 +271,7 @@ describe('processDataMessage', () => { const out = await check({ preview: [ { - date: TIMESTAMP, + date: Long.fromNumber(TIMESTAMP), image: UNPROCESSED_ATTACHMENT, }, ], diff --git a/ts/test-both/util/normalizeNumber_test.ts b/ts/test-both/util/normalizeNumber_test.ts deleted file mode 100644 index b532e96ad..000000000 --- a/ts/test-both/util/normalizeNumber_test.ts +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2021 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import { assert } from 'chai'; -import Long from 'long'; - -import { normalizeNumber } from '../../util/normalizeNumber'; - -describe('normalizeNumber', () => { - it('returns undefined when input is undefined', () => { - assert.isUndefined(normalizeNumber(undefined)); - }); - - it('returns number when input is number', () => { - assert.strictEqual(normalizeNumber(123), 123); - }); - - it('returns number when input is Long', () => { - assert.strictEqual(normalizeNumber(new Long(123)), 123); - }); -}); diff --git a/ts/test-electron/MessageReceiver_test.ts b/ts/test-electron/MessageReceiver_test.ts index ac82035ea..aee724e37 100644 --- a/ts/test-electron/MessageReceiver_test.ts +++ b/ts/test-electron/MessageReceiver_test.ts @@ -5,6 +5,7 @@ import { assert } from 'chai'; import { v4 as getGuid } from 'uuid'; +import Long from 'long'; import MessageReceiver from '../textsecure/MessageReceiver'; import { IncomingWebSocketRequest } from '../textsecure/WebsocketResources'; @@ -48,14 +49,14 @@ describe('MessageReceiver', () => { source: number, sourceUuid: uuid, sourceDevice: deviceId, - timestamp: Date.now(), + timestamp: Long.fromNumber(Date.now()), content: Crypto.getRandomBytes(200), }).finish(); messageReceiver.handleRequest( new IncomingWebSocketRequest( { - id: 1, + id: Long.fromNumber(1), verb: 'PUT', path: '/api/v1/message', body, diff --git a/ts/test-electron/WebsocketResources_test.ts b/ts/test-electron/WebsocketResources_test.ts index b0d1281be..ea71804e3 100644 --- a/ts/test-electron/WebsocketResources_test.ts +++ b/ts/test-electron/WebsocketResources_test.ts @@ -93,7 +93,7 @@ describe('WebSocket-Resource', () => { it('sends requests and receives responses', async () => { // mock socket and request handler - let requestId: number | Long | undefined; + let requestId: Long | undefined; const socket = new FakeSocket(); sinon.stub(socket, 'sendBytes').callsFake((data: Uint8Array) => { diff --git a/ts/textsecure/MessageReceiver.ts b/ts/textsecure/MessageReceiver.ts index 12794d9ea..ec5ea2ff8 100644 --- a/ts/textsecure/MessageReceiver.ts +++ b/ts/textsecure/MessageReceiver.ts @@ -43,7 +43,6 @@ import type { BatcherType } from '../util/batcher'; import { createBatcher } from '../util/batcher'; import { dropNull } from '../util/dropNull'; import { normalizeUuid } from '../util/normalizeUuid'; -import { normalizeNumber } from '../util/normalizeNumber'; import { parseIntOrThrow } from '../util/parseIntOrThrow'; import { clearTimeoutIfNecessary } from '../util/clearTimeoutIfNecessary'; import { Zone } from '../util/Zone'; @@ -279,7 +278,7 @@ export default class MessageReceiver try { const decoded = Proto.Envelope.decode(plaintext); - const serverTimestamp = normalizeNumber(decoded.serverTimestamp); + const serverTimestamp = decoded.serverTimestamp?.toNumber(); const ourUuid = this.storage.user.getCheckedUuid(); @@ -310,7 +309,7 @@ export default class MessageReceiver ) ) : ourUuid, - timestamp: normalizeNumber(decoded.timestamp), + timestamp: decoded.timestamp?.toNumber(), legacyMessage: dropNull(decoded.legacyMessage), content: dropNull(decoded.content), serverGuid: decoded.serverGuid, @@ -690,13 +689,12 @@ export default class MessageReceiver destinationUuid: new UUID( decoded.destinationUuid || item.destinationUuid || ourUuid.toString() ), - timestamp: normalizeNumber(decoded.timestamp), + timestamp: decoded.timestamp?.toNumber(), legacyMessage: dropNull(decoded.legacyMessage), content: dropNull(decoded.content), serverGuid: decoded.serverGuid, - serverTimestamp: normalizeNumber( - item.serverTimestamp || decoded.serverTimestamp - ), + serverTimestamp: + item.serverTimestamp || decoded.serverTimestamp?.toNumber(), }; const { decrypted } = item; @@ -1773,7 +1771,7 @@ export default class MessageReceiver { destination: dropNull(destination), destinationUuid: dropNull(destinationUuid), - timestamp: timestamp ? normalizeNumber(timestamp) : undefined, + timestamp: timestamp?.toNumber(), serverTimestamp: envelope.serverTimestamp, device: envelope.sourceDevice, unidentifiedStatus, @@ -1781,9 +1779,7 @@ export default class MessageReceiver isRecipientUpdate: Boolean(isRecipientUpdate), receivedAtCounter: envelope.receivedAtCounter, receivedAtDate: envelope.receivedAtDate, - expirationStartTimestamp: expirationStartTimestamp - ? normalizeNumber(expirationStartTimestamp) - : undefined, + expirationStartTimestamp: expirationStartTimestamp?.toNumber(), }, this.removeFromCache.bind(this, envelope) ); @@ -2200,7 +2196,7 @@ export default class MessageReceiver receiptMessage.timestamp.map(async rawTimestamp => { const ev = new EventClass( { - timestamp: normalizeNumber(rawTimestamp), + timestamp: rawTimestamp?.toNumber(), envelopeTimestamp: envelope.timestamp, source: envelope.source, sourceUuid: envelope.sourceUuid, @@ -2221,7 +2217,7 @@ export default class MessageReceiver if (envelope.timestamp && typingMessage.timestamp) { const envelopeTimestamp = envelope.timestamp; - const typingTimestamp = normalizeNumber(typingMessage.timestamp); + const typingTimestamp = typingMessage.timestamp?.toNumber(); if (typingTimestamp !== envelopeTimestamp) { log.warn( @@ -2258,7 +2254,7 @@ export default class MessageReceiver senderDevice: envelope.sourceDevice, typing: { typingMessage, - timestamp: timestamp ? normalizeNumber(timestamp) : Date.now(), + timestamp: timestamp?.toNumber() ?? Date.now(), started: action === Proto.TypingMessage.Action.STARTED, stopped: action === Proto.TypingMessage.Action.STOPPED, @@ -2421,7 +2417,7 @@ export default class MessageReceiver log.info( 'sent message to', this.getDestination(sentMessage), - normalizeNumber(sentMessage.timestamp), + sentMessage.timestamp?.toNumber(), 'from', this.getEnvelopeId(envelope) ); @@ -2511,7 +2507,7 @@ export default class MessageReceiver sourceUuid: sync.senderUuid ? normalizeUuid(sync.senderUuid, 'handleViewOnceOpen.senderUuid') : undefined, - timestamp: sync.timestamp ? normalizeNumber(sync.timestamp) : undefined, + timestamp: sync.timestamp?.toNumber(), }, this.removeFromCache.bind(this, envelope) ); @@ -2646,7 +2642,7 @@ export default class MessageReceiver const ev = new ReadSyncEvent( { envelopeTimestamp: envelope.timestamp, - timestamp: normalizeNumber(dropNull(timestamp)), + timestamp: timestamp?.toNumber(), sender: dropNull(sender), senderUuid: senderUuid ? normalizeUuid(senderUuid, 'handleRead.senderUuid') @@ -2669,7 +2665,7 @@ export default class MessageReceiver const ev = new ViewSyncEvent( { envelopeTimestamp: envelope.timestamp, - timestamp: normalizeNumber(dropNull(timestamp)), + timestamp: timestamp?.toNumber(), senderE164: dropNull(senderE164), senderUuid: senderUuid ? normalizeUuid(senderUuid, 'handleViewed.senderUuid') diff --git a/ts/textsecure/SendMessage.ts b/ts/textsecure/SendMessage.ts index f5752eba1..600ec6956 100644 --- a/ts/textsecure/SendMessage.ts +++ b/ts/textsecure/SendMessage.ts @@ -342,7 +342,7 @@ class Message { } const proto = new Proto.DataMessage(); - proto.timestamp = this.timestamp; + proto.timestamp = Long.fromNumber(this.timestamp); proto.attachments = this.attachmentPointers; if (this.body) { @@ -384,7 +384,10 @@ class Message { proto.reaction.emoji = this.reaction.emoji || null; proto.reaction.remove = this.reaction.remove || false; proto.reaction.targetAuthorUuid = this.reaction.targetAuthorUuid || null; - proto.reaction.targetTimestamp = this.reaction.targetTimestamp || null; + proto.reaction.targetTimestamp = + this.reaction.targetTimestamp === undefined + ? null + : Long.fromNumber(this.reaction.targetTimestamp); } if (Array.isArray(this.preview)) { @@ -407,7 +410,8 @@ class Message { proto.quote = new Quote(); const { quote } = proto; - quote.id = this.quote.id || null; + quote.id = + this.quote.id === undefined ? null : Long.fromNumber(this.quote.id); quote.authorUuid = this.quote.authorUuid || null; quote.text = this.quote.text || null; quote.attachments = (this.quote.attachments || []).map( @@ -453,7 +457,7 @@ class Message { } if (this.deletedForEveryoneTimestamp) { proto.delete = { - targetSentTimestamp: this.deletedForEveryoneTimestamp, + targetSentTimestamp: Long.fromNumber(this.deletedForEveryoneTimestamp), }; } if (this.mentions) { @@ -484,7 +488,7 @@ class Message { if (this.storyContext.authorUuid) { storyContext.authorUuid = this.storyContext.authorUuid; } - storyContext.sentTimestamp = this.storyContext.timestamp; + storyContext.sentTimestamp = Long.fromNumber(this.storyContext.timestamp); proto.storyContext = storyContext; } @@ -772,7 +776,7 @@ export default class MessageSender { typingMessage.groupId = groupId; } typingMessage.action = action; - typingMessage.timestamp = finalTimestamp; + typingMessage.timestamp = Long.fromNumber(finalTimestamp); const contentMessage = new Proto.Content(); contentMessage.typingMessage = typingMessage; @@ -1111,7 +1115,7 @@ export default class MessageSender { const dataMessage = Proto.DataMessage.decode(encodedDataMessage); const sentMessage = new Proto.SyncMessage.Sent(); - sentMessage.timestamp = timestamp; + sentMessage.timestamp = Long.fromNumber(timestamp); sentMessage.message = dataMessage; if (destination) { sentMessage.destination = destination; @@ -1120,7 +1124,9 @@ export default class MessageSender { sentMessage.destinationUuid = destinationUuid; } if (expirationStartTimestamp) { - sentMessage.expirationStartTimestamp = expirationStartTimestamp; + sentMessage.expirationStartTimestamp = Long.fromNumber( + expirationStartTimestamp + ); } if (isUpdate) { @@ -1345,7 +1351,10 @@ export default class MessageSender { const syncMessage = this.createSyncMessage(); syncMessage.read = []; for (let i = 0; i < reads.length; i += 1) { - const proto = new Proto.SyncMessage.Read(reads[i]); + const proto = new Proto.SyncMessage.Read({ + ...reads[i], + timestamp: Long.fromNumber(reads[i].timestamp), + }); syncMessage.read.push(proto); } @@ -1374,7 +1383,13 @@ export default class MessageSender { const myUuid = window.textsecure.storage.user.getCheckedUuid(); const syncMessage = this.createSyncMessage(); - syncMessage.viewed = views.map(view => new Proto.SyncMessage.Viewed(view)); + syncMessage.viewed = views.map( + view => + new Proto.SyncMessage.Viewed({ + ...view, + timestamp: Long.fromNumber(view.timestamp), + }) + ); const contentMessage = new Proto.Content(); contentMessage.syncMessage = syncMessage; @@ -1417,7 +1432,7 @@ export default class MessageSender { viewOnceOpen.sender = senderE164; } viewOnceOpen.senderUuid = senderUuid; - viewOnceOpen.timestamp = timestamp; + viewOnceOpen.timestamp = Long.fromNumber(timestamp); syncMessage.viewOnceOpen = viewOnceOpen; const contentMessage = new Proto.Content(); @@ -1647,7 +1662,9 @@ export default class MessageSender { const receiptMessage = new Proto.ReceiptMessage(); receiptMessage.type = type; - receiptMessage.timestamp = timestamps; + receiptMessage.timestamp = timestamps.map(timestamp => + Long.fromNumber(timestamp) + ); const contentMessage = new Proto.Content(); contentMessage.receiptMessage = receiptMessage; diff --git a/ts/textsecure/WebsocketResources.ts b/ts/textsecure/WebsocketResources.ts index a9e1e48c2..2878c8e69 100644 --- a/ts/textsecure/WebsocketResources.ts +++ b/ts/textsecure/WebsocketResources.ts @@ -24,6 +24,7 @@ */ import type { connection as WebSocket, IMessage } from 'websocket'; +import Long from 'long'; import type { EventHandler } from './EventTarget'; import EventTarget from './EventTarget'; @@ -32,7 +33,6 @@ import * as durations from '../util/durations'; import { dropNull } from '../util/dropNull'; import { isOlderThan } from '../util/timestamp'; import { strictAssert } from '../util/assert'; -import { normalizeNumber } from '../util/normalizeNumber'; import * as Errors from '../types/errors'; import { SignalService as Proto } from '../protobuf'; import * as log from '../logging/log'; @@ -43,7 +43,7 @@ const THIRTY_SECONDS = 30 * durations.SECOND; const MAX_MESSAGE_SIZE = 256 * 1024; export class IncomingWebSocketRequest { - private readonly id: Long | number; + private readonly id: Long; public readonly verb: string; @@ -105,18 +105,18 @@ export class CloseEvent extends Event { } export default class WebSocketResource extends EventTarget { - private outgoingId = 1; + private outgoingId = Long.fromNumber(1, true); private closed = false; private readonly outgoingMap = new Map< - number, + string, (result: SendRequestResult) => void >(); private readonly boundOnMessage: (message: IMessage) => void; - private activeRequests = new Set(); + private activeRequests = new Set(); private shuttingDown = false; @@ -176,10 +176,11 @@ export default class WebSocketResource extends EventTarget { options: SendRequestOptions ): Promise { const id = this.outgoingId; - strictAssert(!this.outgoingMap.has(id), 'Duplicate outgoing request'); + const idString = id.toString(); + strictAssert(!this.outgoingMap.has(idString), 'Duplicate outgoing request'); - // eslint-disable-next-line no-bitwise - this.outgoingId = Math.max(1, (this.outgoingId + 1) & 0x7fffffff); + // Note that this automatically wraps + this.outgoingId = this.outgoingId.add(1); const bytes = Proto.WebSocketMessage.encode({ type: Proto.WebSocketMessage.Type.REQUEST, @@ -197,22 +198,22 @@ export default class WebSocketResource extends EventTarget { ); strictAssert(!this.shuttingDown, 'Cannot send request, shutting down'); - this.addActive(id); + this.addActive(idString); const promise = new Promise((resolve, reject) => { let timer = options.timeout ? Timers.setTimeout(() => { - this.removeActive(id); + this.removeActive(idString); reject(new Error('Request timed out')); }, options.timeout) : undefined; - this.outgoingMap.set(id, result => { + this.outgoingMap.set(idString, result => { if (timer !== undefined) { Timers.clearTimeout(timer); timer = undefined; } - this.removeActive(id); + this.removeActive(idString); resolve(result); }); }); @@ -321,12 +322,12 @@ export default class WebSocketResource extends EventTarget { const { response } = message; strictAssert(response.id, 'response without id'); - const responseId = normalizeNumber(response.id); - const resolve = this.outgoingMap.get(responseId); - this.outgoingMap.delete(responseId); + const responseIdString = response.id.toString(); + const resolve = this.outgoingMap.get(responseIdString); + this.outgoingMap.delete(responseIdString); if (!resolve) { - throw new Error(`Received response for unknown request ${responseId}`); + throw new Error(`Received response for unknown request ${response.id}`); } resolve({ @@ -352,11 +353,11 @@ export default class WebSocketResource extends EventTarget { } } - private addActive(request: IncomingWebSocketRequest | number): void { + private addActive(request: IncomingWebSocketRequest | string): void { this.activeRequests.add(request); } - private removeActive(request: IncomingWebSocketRequest | number): void { + private removeActive(request: IncomingWebSocketRequest | string): void { if (!this.activeRequests.has(request)) { log.warn('WebSocketResource: removing unknown request'); return; diff --git a/ts/textsecure/processDataMessage.ts b/ts/textsecure/processDataMessage.ts index c572875e0..d89b1dcd5 100644 --- a/ts/textsecure/processDataMessage.ts +++ b/ts/textsecure/processDataMessage.ts @@ -5,7 +5,6 @@ import Long from 'long'; import { assert, strictAssert } from '../util/assert'; import { dropNull, shallowDropNull } from '../util/dropNull'; -import { normalizeNumber } from '../util/normalizeNumber'; import { SignalService as Proto } from '../protobuf'; import { deriveGroupFields } from '../groups'; import * as Bytes from '../Bytes'; @@ -120,7 +119,7 @@ export function processQuote( } return { - id: normalizeNumber(dropNull(quote.id)), + id: quote.id?.toNumber(), authorUuid: dropNull(quote.authorUuid), text: dropNull(quote.text), attachments: (quote.attachments ?? []).map(attachment => { @@ -163,10 +162,8 @@ function isLinkPreviewDateValid(value: unknown): value is number { ); } -function cleanLinkPreviewDate( - value?: Long | number | null -): number | undefined { - const result = normalizeNumber(value ?? undefined); +function cleanLinkPreviewDate(value?: Long | null): number | undefined { + const result = value?.toNumber(); return isLinkPreviewDateValid(result) ? result : undefined; } @@ -198,7 +195,7 @@ export function processSticker( return { packId: sticker.packId ? Bytes.toHex(sticker.packId) : undefined, packKey: sticker.packKey ? Bytes.toBase64(sticker.packKey) : undefined, - stickerId: normalizeNumber(dropNull(sticker.stickerId)), + stickerId: dropNull(sticker.stickerId), data: processAttachment(sticker.data), }; } @@ -214,7 +211,7 @@ export function processReaction( emoji: dropNull(reaction.emoji), remove: Boolean(reaction.remove), targetAuthorUuid: dropNull(reaction.targetAuthorUuid), - targetTimestamp: normalizeNumber(dropNull(reaction.targetTimestamp)), + targetTimestamp: reaction.targetTimestamp?.toNumber(), }; } @@ -226,7 +223,7 @@ export function processDelete( } return { - targetSentTimestamp: normalizeNumber(dropNull(del.targetSentTimestamp)), + targetSentTimestamp: del.targetSentTimestamp?.toNumber(), }; } @@ -245,7 +242,7 @@ export async function processDataMessage( throw new Error('Missing timestamp on dataMessage'); } - const timestamp = normalizeNumber(message.timestamp); + const timestamp = message.timestamp?.toNumber(); if (envelopeTimestamp !== timestamp) { throw new Error( @@ -272,9 +269,7 @@ export async function processDataMessage( contact: processContact(message.contact), preview: processPreview(message.preview), sticker: processSticker(message.sticker), - requiredProtocolVersion: normalizeNumber( - dropNull(message.requiredProtocolVersion) - ), + requiredProtocolVersion: dropNull(message.requiredProtocolVersion), isViewOnce: Boolean(message.isViewOnce), reaction: processReaction(message.reaction), delete: processDelete(message.delete), diff --git a/ts/util/normalizeNumber.ts b/ts/util/normalizeNumber.ts deleted file mode 100644 index 643dbdd86..000000000 --- a/ts/util/normalizeNumber.ts +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2021 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -export function normalizeNumber(value: number | Long): number; -export function normalizeNumber(value?: number | Long): number | undefined; - -export function normalizeNumber(value?: number | Long): number | undefined { - if (value === undefined) { - return undefined; - } - - if (typeof value === 'number') { - return value; - } - - return value.toNumber(); -} diff --git a/ts/util/timestampLongUtils.ts b/ts/util/timestampLongUtils.ts index 79921821b..7cd348451 100644 --- a/ts/util/timestampLongUtils.ts +++ b/ts/util/timestampLongUtils.ts @@ -3,8 +3,6 @@ import Long from 'long'; -import { normalizeNumber } from './normalizeNumber'; - export function getSafeLongFromTimestamp(timestamp = 0): Long { if (timestamp >= Number.MAX_SAFE_INTEGER) { return Long.MAX_VALUE; @@ -13,12 +11,12 @@ export function getSafeLongFromTimestamp(timestamp = 0): Long { return Long.fromNumber(timestamp); } -export function getTimestampFromLong(value?: Long | number | null): number { +export function getTimestampFromLong(value?: Long | null): number { if (!value) { return 0; } - const num = normalizeNumber(value); + const num = value.toNumber(); if (num >= Number.MAX_SAFE_INTEGER) { return Number.MAX_SAFE_INTEGER;