diff --git a/ts/Bytes.ts b/ts/Bytes.ts index 35b10935f36e..d7894cffe8c7 100644 --- a/ts/Bytes.ts +++ b/ts/Bytes.ts @@ -63,3 +63,7 @@ export function areEqual( ): boolean { return bytes.areEqual(a, b); } + +export function readBigUint64BE(value: Uint8Array): bigint { + return bytes.readBigUint64BE(value); +} diff --git a/ts/RemoteConfig.ts b/ts/RemoteConfig.ts index 87674cd83ac0..574b8c51d145 100644 --- a/ts/RemoteConfig.ts +++ b/ts/RemoteConfig.ts @@ -8,8 +8,8 @@ import * as log from './logging/log'; import type { UUIDStringType } from './types/UUID'; import { parseIntOrThrow } from './util/parseIntOrThrow'; import { SECOND, HOUR } from './util/durations'; +import { uuidToBytes } from './util/uuidToBytes'; import * as Bytes from './Bytes'; -import { hash, uuidToBytes } from './Crypto'; import { HashType } from './types/Crypto'; import { getCountryCode } from './types/PhoneNumber'; @@ -234,8 +234,10 @@ export function getBucketValue(uuid: UUIDStringType, flagName: string): number { Bytes.fromString(`${flagName}.`), uuidToBytes(uuid), ]); - const hashResult = hash(HashType.size256, hashInput); - const buffer = Buffer.from(hashResult.slice(0, 8)); + const hashResult = window.SignalContext.crypto.hash( + HashType.size256, + hashInput + ); - return Number(buffer.readBigUint64BE() % 1_000_000n); + return Number(Bytes.readBigUint64BE(hashResult.slice(0, 8)) % 1_000_000n); } diff --git a/ts/context/Bytes.ts b/ts/context/Bytes.ts index e69a547dd626..d6bfb95f2bb1 100644 --- a/ts/context/Bytes.ts +++ b/ts/context/Bytes.ts @@ -67,4 +67,9 @@ export class Bytes { return Buffer.compare(a, b) === 0; } + + public readBigUint64BE(value: Uint8Array): bigint { + const buffer = Buffer.from(value); + return buffer.readBigUint64BE(); + } } diff --git a/ts/state/ducks/calling.ts b/ts/state/ducks/calling.ts index 935971ee704e..97d0e3b9a4b0 100644 --- a/ts/state/ducks/calling.ts +++ b/ts/state/ducks/calling.ts @@ -57,6 +57,7 @@ import { singleProtoJobQueue } from '../../jobs/singleProtoJobQueue'; import MessageSender from '../../textsecure/SendMessage'; import type { BoundActionCreatorsMapObject } from '../../hooks/useBoundActions'; import { useBoundActions } from '../../hooks/useBoundActions'; +import { isAnybodyElseInGroupCall } from './callingHelpers'; // State @@ -297,33 +298,6 @@ export const getActiveCall = ({ activeCallState && getOwn(callsByConversation, activeCallState.conversationId); -// In theory, there could be multiple incoming calls, or an incoming call while there's -// an active call. In practice, the UI is not ready for this, and RingRTC doesn't -// support it for direct calls. -export const getIncomingCall = ( - callsByConversation: Readonly, - ourUuid: UUIDStringType -): undefined | DirectCallStateType | GroupCallStateType => - Object.values(callsByConversation).find(call => { - switch (call.callMode) { - case CallMode.Direct: - return call.isIncoming && call.callState === CallState.Ringing; - case CallMode.Group: - return ( - call.ringerUuid && - call.connectionState === GroupCallConnectionState.NotConnected && - isAnybodyElseInGroupCall(call.peekInfo, ourUuid) - ); - default: - throw missingCaseError(call); - } - }); - -export const isAnybodyElseInGroupCall = ( - peekInfo: undefined | Readonly>, - ourUuid: UUIDStringType -): boolean => Boolean(peekInfo?.uuids.some(id => id !== ourUuid)); - const getGroupCallRingState = ( call: Readonly ): GroupCallRingStateType => diff --git a/ts/state/ducks/callingHelpers.ts b/ts/state/ducks/callingHelpers.ts new file mode 100644 index 000000000000..9b2273ae9f0b --- /dev/null +++ b/ts/state/ducks/callingHelpers.ts @@ -0,0 +1,45 @@ +// Copyright 2023 Signal Messenger, LLC +// SPDX-License-Identifier: AGPL-3.0-only + +// Note that this file should not important any binary addons or Node.js modules +// because it can be imported by storybook +import { + CallMode, + CallState, + GroupCallConnectionState, +} from '../../types/Calling'; +import type { UUIDStringType } from '../../types/UUID'; +import { missingCaseError } from '../../util/missingCaseError'; +import type { + DirectCallStateType, + CallsByConversationType, + GroupCallPeekInfoType, + GroupCallStateType, +} from './calling'; + +// In theory, there could be multiple incoming calls, or an incoming call while there's +// an active call. In practice, the UI is not ready for this, and RingRTC doesn't +// support it for direct calls. +export const getIncomingCall = ( + callsByConversation: Readonly, + ourUuid: UUIDStringType +): undefined | DirectCallStateType | GroupCallStateType => + Object.values(callsByConversation).find(call => { + switch (call.callMode) { + case CallMode.Direct: + return call.isIncoming && call.callState === CallState.Ringing; + case CallMode.Group: + return ( + call.ringerUuid && + call.connectionState === GroupCallConnectionState.NotConnected && + isAnybodyElseInGroupCall(call.peekInfo, ourUuid) + ); + default: + throw missingCaseError(call); + } + }); + +export const isAnybodyElseInGroupCall = ( + peekInfo: undefined | Readonly>, + ourUuid: UUIDStringType +): boolean => Boolean(peekInfo?.uuids.some(id => id !== ourUuid)); diff --git a/ts/state/selectors/calling.ts b/ts/state/selectors/calling.ts index 6a63a76c1b68..25c92405a9d0 100644 --- a/ts/state/selectors/calling.ts +++ b/ts/state/selectors/calling.ts @@ -11,7 +11,7 @@ import type { DirectCallStateType, GroupCallStateType, } from '../ducks/calling'; -import { getIncomingCall as getIncomingCallHelper } from '../ducks/calling'; +import { getIncomingCall as getIncomingCallHelper } from '../ducks/callingHelpers'; import { getUserACI } from './user'; import { getOwn } from '../../util/getOwn'; import { CallViewMode } from '../../types/Calling'; diff --git a/ts/state/smart/ConversationHeader.tsx b/ts/state/smart/ConversationHeader.tsx index 575c0aa37d33..c008b7de2697 100644 --- a/ts/state/smart/ConversationHeader.tsx +++ b/ts/state/smart/ConversationHeader.tsx @@ -17,11 +17,8 @@ import { isMissingRequiredProfileSharing, } from '../selectors/conversations'; import { CallMode } from '../../types/Calling'; -import { - getActiveCall, - isAnybodyElseInGroupCall, - useCallingActions, -} from '../ducks/calling'; +import { getActiveCall, useCallingActions } from '../ducks/calling'; +import { isAnybodyElseInGroupCall } from '../ducks/callingHelpers'; import { getConversationCallMode, useConversationsActions, diff --git a/ts/test-electron/state/ducks/calling_test.ts b/ts/test-electron/state/ducks/calling_test.ts index 4eb6931c41fe..3d5fd379dfb1 100644 --- a/ts/test-electron/state/ducks/calling_test.ts +++ b/ts/test-electron/state/ducks/calling_test.ts @@ -15,9 +15,9 @@ import { actions, getActiveCall, getEmptyState, - isAnybodyElseInGroupCall, reducer, } from '../../../state/ducks/calling'; +import { isAnybodyElseInGroupCall } from '../../../state/ducks/callingHelpers'; import { truncateAudioLevel } from '../../../calling/truncateAudioLevel'; import { calling as callingService } from '../../../services/calling'; import {