diff --git a/lib/components/peer-olm-session-creator-provider.react.js b/lib/components/peer-olm-session-creator-provider.react.js --- a/lib/components/peer-olm-session-creator-provider.react.js +++ b/lib/components/peer-olm-session-creator-provider.react.js @@ -7,14 +7,13 @@ import { useTunnelbroker } from '../tunnelbroker/tunnelbroker-context.js'; import { createOlmSessionsWithUser, - type SessionCreationOptions, + type DeviceSessionCreationRequest, } from '../utils/crypto-utils.js'; export type PeerOlmSessionCreatorContextType = { - +createOlmSessionsWithPeer: ( + +createOlmSessionsWithUser: ( userID: string, - deviceID: string, - sessionCreationOptions?: SessionCreationOptions, + devices: $ReadOnlyArray, ) => Promise, }; @@ -35,19 +34,19 @@ [userID: string]: { [deviceID: string]: ?Promise }, }>({}); - const createOlmSessionsWithPeer = React.useCallback( - ( + const createOlmSessionsWithUserCallback = React.useCallback( + async ( userID: string, - deviceID: string, - sessionCreationOptions?: SessionCreationOptions, + devices: $ReadOnlyArray, ) => { - if ( - runningPromises.current[userID] && - runningPromises.current[userID][deviceID] - ) { - return runningPromises.current[userID][deviceID]; + if (!runningPromises.current[userID]) { + runningPromises.current[userID] = {}; } + const filteredDevices = devices.filter( + request => !runningPromises.current[userID][request.deviceID], + ); + const promise = (async () => { const authMetadata = await getAuthMetadata(); await createOlmSessionsWithUser( @@ -55,26 +54,36 @@ identityClient, sendMessageToDevice, userID, - [{ deviceID, sessionCreationOptions }], + filteredDevices, ); - runningPromises.current[userID][deviceID] = null; + for (const request of filteredDevices) { + runningPromises.current[userID][request.deviceID] = null; + } })(); - if (!runningPromises.current[userID]) { - runningPromises.current[userID] = {}; + for (const request of filteredDevices) { + runningPromises.current[userID][request.deviceID] = promise; + } + + const promises = []; + for (const request of devices) { + if (runningPromises.current[userID][request.deviceID]) { + promises.push(runningPromises.current[userID][request.deviceID]); + } } - runningPromises.current[userID][deviceID] = promise; - return promise; + await Promise.all(promises); }, [identityClient, sendMessageToDevice, getAuthMetadata], ); const peerOlmSessionCreatorContextValue: PeerOlmSessionCreatorContextType = React.useMemo( - () => ({ createOlmSessionsWithPeer }), - [createOlmSessionsWithPeer], + () => ({ + createOlmSessionsWithUser: createOlmSessionsWithUserCallback, + }), + [createOlmSessionsWithUserCallback], ); return ( diff --git a/lib/push/send-hooks.react.js b/lib/push/send-hooks.react.js --- a/lib/push/send-hooks.react.js +++ b/lib/push/send-hooks.react.js @@ -109,7 +109,7 @@ const userInfos = useSelector(state => state.userStore.userInfos); const { getENSNames } = React.useContext(ENSCacheContext); const getFCNames = React.useContext(NeynarClientContext)?.getFCNames; - const { createOlmSessionsWithPeer: olmSessionCreator } = + const { createOlmSessionsWithUser: olmSessionCreator } = usePeerOlmSessionsCreatorContext(); const { sendNotif } = useTunnelbroker(); const { encryptedNotifUtilsAPI } = getConfig(); diff --git a/lib/push/send-utils.js b/lib/push/send-utils.js --- a/lib/push/send-utils.js +++ b/lib/push/send-utils.js @@ -62,6 +62,7 @@ import type { ThickRawThreadInfos } from '../types/thread-types.js'; import type { UserInfos } from '../types/user-types.js'; import { getConfig } from '../utils/config.js'; +import type { DeviceSessionCreationRequest } from '../utils/crypto-utils.js'; import { type GetENSNames } from '../utils/ens-helpers.js'; import { type GetFCNames } from '../utils/farcaster-helpers.js'; import { promiseAll } from '../utils/promises.js'; @@ -965,7 +966,10 @@ deviceIDsToUserIDs: { +[string]: string, }, - olmSessionCreator: (userID: string, deviceID: string) => Promise, + olmSessionCreator: ( + userID: string, + devices: $ReadOnlyArray, + ) => Promise, ): Promise { const { initializeCryptoAccount, @@ -984,7 +988,7 @@ continue; } olmSessionCreationPromises.push( - olmSessionCreator(deviceIDsToUserIDs[deviceID], deviceID), + olmSessionCreator(deviceIDsToUserIDs[deviceID], [{ deviceID }]), ); } @@ -1033,7 +1037,10 @@ type PreparePushNotifsInputData = { +encryptedNotifUtilsAPI: EncryptedNotifUtilsAPI, +senderDeviceDescriptor: SenderDeviceDescriptor, - +olmSessionCreator: (userID: string, deviceID: string) => Promise, + +olmSessionCreator: ( + userID: string, + devices: $ReadOnlyArray, + ) => Promise, +messageInfos: { +[id: string]: RawMessageInfo }, +thickRawThreadInfos: ThickRawThreadInfos, +auxUserInfos: AuxUserInfos, @@ -1095,7 +1102,10 @@ type PrepareOwnDevicesPushNotifsInputData = { +encryptedNotifUtilsAPI: EncryptedNotifUtilsAPI, +senderInfo: SenderInfo, - +olmSessionCreator: (userID: string, deviceID: string) => Promise, + +olmSessionCreator: ( + userID: string, + devices: $ReadOnlyArray, + ) => Promise, +auxUserInfos: AuxUserInfos, +rescindData?: { threadID: string }, +badgeUpdateData?: { threadID: string }, diff --git a/lib/tunnelbroker/peer-to-peer-context.js b/lib/tunnelbroker/peer-to-peer-context.js --- a/lib/tunnelbroker/peer-to-peer-context.js +++ b/lib/tunnelbroker/peer-to-peer-context.js @@ -25,6 +25,7 @@ peerToPeerMessageTypes, } from '../types/tunnelbroker/peer-to-peer-message-types.js'; import { getConfig } from '../utils/config.js'; +import type { DeviceSessionCreationRequest } from '../utils/crypto-utils.js'; import { getMessageForException } from '../utils/errors.js'; import { entries } from '../utils/objects.js'; import { olmSessionErrors } from '../utils/olm-utils.js'; @@ -66,7 +67,10 @@ messageID: ?string, ) => Promise, identityContext: IdentityClientContextType, - peerOlmSessionsCreator: (userID: string, deviceID: string) => Promise, + peerOlmSessionsCreator: ( + userID: string, + devices: $ReadOnlyArray, + ) => Promise, messageIDs: ?$ReadOnlyArray, ): Promise { let authMetadata; @@ -175,7 +179,9 @@ break; } try { - await peerOlmSessionsCreator(message.userID, peerDeviceID); + await peerOlmSessionsCreator(message.userID, [ + { deviceID: peerDeviceID }, + ]); const result = await olmAPI.encryptAndPersist( message.plaintext, message.deviceID, @@ -264,7 +270,7 @@ >([]); const promiseRunning = React.useRef(false); - const { createOlmSessionsWithPeer: peerOlmSessionsCreator } = + const { createOlmSessionsWithUser: peerOlmSessionsCreator } = usePeerOlmSessionsCreatorContext(); const sendPushNotifs = useSendPushNotifs(); @@ -371,7 +377,9 @@ return; } try { - await peerOlmSessionsCreator(recipient.userID, recipient.deviceID); + await peerOlmSessionsCreator(recipient.userID, [ + { deviceID: recipient.deviceID }, + ]); const encryptedData = await olmAPI.encrypt( contentPayload, recipient.deviceID, diff --git a/lib/tunnelbroker/use-peer-to-peer-message-handler.js b/lib/tunnelbroker/use-peer-to-peer-message-handler.js --- a/lib/tunnelbroker/use-peer-to-peer-message-handler.js +++ b/lib/tunnelbroker/use-peer-to-peer-message-handler.js @@ -192,7 +192,7 @@ const handleOlmMessageToDevice = useHandleOlmMessageToDevice(); const resendPeerToPeerMessages = useResendPeerToPeerMessages(); - const { createOlmSessionsWithPeer } = usePeerOlmSessionsCreatorContext(); + const { createOlmSessionsWithUser } = usePeerOlmSessionsCreatorContext(); return React.useCallback( async (message: PeerToPeerMessage, messageID: string) => { @@ -311,13 +311,12 @@ throw e; } - await createOlmSessionsWithPeer( - message.senderInfo.userID, - message.senderInfo.deviceID, + await createOlmSessionsWithUser(message.senderInfo.userID, [ { - overwriteContentSession: true, + deviceID: message.senderInfo.deviceID, + sessionCreationOptions: { overwriteContentSession: true }, }, - ); + ]); await resendPeerToPeerMessages(message.senderInfo.deviceID); } } else if (message.type === peerToPeerMessageTypes.REFRESH_KEY_REQUEST) { @@ -410,7 +409,7 @@ }, [ broadcastDeviceListUpdates, - createOlmSessionsWithPeer, + createOlmSessionsWithUser, dispatch, foreignPeerDevices, getAndUpdateDeviceListsForUsers,