diff --git a/lib/hooks/peer-list-hooks.js b/lib/hooks/peer-list-hooks.js --- a/lib/hooks/peer-list-hooks.js +++ b/lib/hooks/peer-list-hooks.js @@ -17,7 +17,10 @@ type DeviceListUpdated, peerToPeerMessageTypes, } from '../types/tunnelbroker/peer-to-peer-message-types.js'; -import { getContentSigningKey } from '../utils/crypto-utils.js'; +import { + getContentSigningKey, + createOlmSessionWithPeer, +} from '../utils/crypto-utils.js'; import { convertSignedDeviceListsToRawDeviceLists } from '../utils/device-list-utils.js'; import { values } from '../utils/objects.js'; import { useDispatch, useSelector } from '../utils/redux-utils.js'; @@ -131,8 +134,34 @@ ); } +function useOlmSessionCreation(): ( + userID: string, + deviceID: string, +) => Promise { + const identityContext = React.useContext(IdentityClientContext); + invariant(identityContext, 'Identity context should be set'); + const { getAuthMetadata, identityClient } = identityContext; + + const { sendMessage } = useTunnelbroker(); + + return React.useCallback( + async (userID: string, deviceID: string) => { + const authMetadata = await getAuthMetadata(); + return createOlmSessionWithPeer( + authMetadata, + identityClient, + sendMessage, + userID, + deviceID, + ); + }, + [getAuthMetadata, identityClient, sendMessage], + ); +} + export { useGetDeviceListsForUsers, useBroadcastDeviceListUpdates, useGetAndUpdateDeviceListsForUsers, + useOlmSessionCreation, }; diff --git a/lib/utils/crypto-utils.js b/lib/utils/crypto-utils.js --- a/lib/utils/crypto-utils.js +++ b/lib/utils/crypto-utils.js @@ -106,6 +106,9 @@ } } +// TODO: This must be exposed via context to make sure +// there are no two promises running at the same time +// the same device async function createOlmSessionWithPeer( authMetadata: AuthMetadata, identityClient: IdentityServiceClient, @@ -115,6 +118,14 @@ ): Promise { const { olmAPI } = getConfig(); await olmAPI.initializeCryptoAccount(); + const [hasContentSession, hasNotifsSession] = await Promise.all([ + olmAPI.isContentSessionInitialized(deviceID), + olmAPI.isPeerNotificationsSessionInitialized(deviceID), + ]); + + if (hasContentSession && hasNotifsSession) { + return; + } const { userID: authUserID, @@ -134,14 +145,30 @@ } const { keys } = deviceKeysResponse; - const { primaryIdentityPublicKeys } = keys.identityKeysBlob; + const { primaryIdentityPublicKeys, notificationIdentityPublicKeys } = + keys.identityKeysBlob; const recipientDeviceID = primaryIdentityPublicKeys.ed25519; - const { sessionVersion, encryptedData } = - await olmAPI.contentOutboundSessionCreator( + if (hasContentSession) { + await olmAPI.notificationsOutboundSessionCreator( + notificationIdentityPublicKeys, primaryIdentityPublicKeys, - keys.contentInitializationInfo, + keys.notifInitializationInfo, ); + return; + } + + const [{ sessionVersion, encryptedData }] = await Promise.all([ + olmAPI.contentOutboundSessionCreator( + primaryIdentityPublicKeys, + keys.contentInitializationInfo, + ), + olmAPI.notificationsOutboundSessionCreator( + notificationIdentityPublicKeys, + primaryIdentityPublicKeys, + keys.notifInitializationInfo, + ), + ]); const sessionCreationMessage: OutboundSessionCreation = { type: peerToPeerMessageTypes.OUTBOUND_SESSION_CREATION,