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 @@ -8,6 +8,7 @@ import { removePeerUsersActionType } from '../actions/aux-user-actions.js'; import { invalidateTunnelbrokerDeviceTokenActionType } from '../actions/tunnelbroker-actions.js'; import { logOutActionTypes, useLogOut } from '../actions/user-actions.js'; +import { usePeerOlmSessionsCreatorContext } from '../components/peer-olm-session-creator-provider.react.js'; import { useBroadcastDeviceListUpdates, useBroadcastAccountDeletion, @@ -37,7 +38,11 @@ import { getConfig } from '../utils/config.js'; import { getContentSigningKey } from '../utils/crypto-utils.js'; import { getMessageForException } from '../utils/errors.js'; -import { hasHigherDeviceID, olmSessionErrors } from '../utils/olm-utils.js'; +import { + hasHigherDeviceID, + OLM_SESSION_ERROR_PREFIX, + olmSessionErrors, +} from '../utils/olm-utils.js'; import { getClientMessageIDFromTunnelbrokerMessageID } from '../utils/peer-to-peer-communication-utils.js'; import { useDispatchActionPromise } from '../utils/redux-promise-utils.js'; import { useDispatch, useSelector } from '../utils/redux-utils.js'; @@ -173,6 +178,7 @@ const handleOlmMessageToDevice = useHandleOlmMessageToDevice(); const resendPeerToPeerMessages = useResendPeerToPeerMessages(); + const { createOlmSessionsWithPeer } = usePeerOlmSessionsCreatorContext(); return React.useCallback( async (message: PeerToPeerMessage, messageID: string) => { @@ -270,17 +276,30 @@ console.log('Failed processing Olm P2P message:', e); } } catch (e) { - if (e.message?.includes(olmSessionErrors.messageAlreadyDecrypted)) { + if (e.message?.includes(olmSessionErrors.invalidSessionVersion)) { console.log( - 'Received already decrypted message from device ' + + 'Received message decrypted with different session from ' + `${message.senderInfo.deviceID}.`, ); - } else { - console.log( - 'Error decrypting message from device ' + - `${message.senderInfo.deviceID}: ${e.message}`, - ); + return; + } + console.log( + 'Error decrypting message from device ' + + `${message.senderInfo.deviceID}: ${e.message}`, + ); + + if (!e.message?.includes(OLM_SESSION_ERROR_PREFIX)) { + throw e; } + + await createOlmSessionsWithPeer( + message.senderInfo.userID, + message.senderInfo.deviceID, + { + overwriteContentSession: true, + }, + ); + await resendPeerToPeerMessages(message.senderInfo.deviceID); } } else if (message.type === peerToPeerMessageTypes.REFRESH_KEY_REQUEST) { try { @@ -375,6 +394,7 @@ }, [ broadcastDeviceListUpdates, + createOlmSessionsWithPeer, dispatch, foreignPeerDevices, getAndUpdateDeviceListsForUsers, diff --git a/lib/utils/olm-utils.js b/lib/utils/olm-utils.js --- a/lib/utils/olm-utils.js +++ b/lib/utils/olm-utils.js @@ -116,17 +116,14 @@ return { identityKeys, prekey, prekeySignature }; } +export const OLM_SESSION_ERROR_PREFIX = 'OLM_'; const olmSessionErrors = Object.freeze({ // Two clients send the session request to each other at the same time, // we choose which session to keep based on `deviceID`. - raceCondition: 'OLM_SESSION_CREATION_RACE_CONDITION', + raceCondition: `${OLM_SESSION_ERROR_PREFIX}SESSION_CREATION_RACE_CONDITION`, // The client received a session request with a lower session version, // this request can be ignored. - alreadyCreated: 'OLM_SESSION_ALREADY_CREATED', - // If using sequential decrypt this error means that message was decrypted. - // Otherwise, it could mean that the receiver chain advance beyond and the key - // to decrypt that message was discarded. - messageAlreadyDecrypted: 'OLM_ALREADY_DECRYPTED_OR_KEYS_SKIPPED', + alreadyCreated: `${OLM_SESSION_ERROR_PREFIX}SESSION_ALREADY_CREATED`, // Error thrown when attempting to encrypt/decrypt, indicating that // the session for a given deviceID is not created. // This definition should remain in sync with the value defined in