Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F3381976
D12372.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
18 KB
Referenced Files
None
Subscribers
None
D12372.diff
View Options
diff --git a/lib/handlers/peer-to-peer-message-handler.js b/lib/handlers/peer-to-peer-message-handler.js
deleted file mode 100644
--- a/lib/handlers/peer-to-peer-message-handler.js
+++ /dev/null
@@ -1,212 +0,0 @@
-// @flow
-
-import _isEqual from 'lodash/fp/isEqual.js';
-
-import {
- verifyAndGetDeviceList,
- removeDeviceFromDeviceList,
-} from '../shared/device-list-utils.js';
-import type {
- IdentityServiceClient,
- DeviceOlmInboundKeys,
-} from '../types/identity-service-types.js';
-import {
- peerToPeerMessageTypes,
- type PeerToPeerMessage,
-} from '../types/tunnelbroker/peer-to-peer-message-types.js';
-import { secondaryDeviceLogoutP2PMessageValidator } from '../types/tunnelbroker/user-actions-peer-to-peer-message-types.js';
-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 { getClientMessageIDFromTunnelbrokerMessageID } from '../utils/peer-to-peer-communication-utils.js';
-
-async function peerToPeerMessageHandler(
- message: PeerToPeerMessage,
- identityClient: IdentityServiceClient,
- messageID: string,
-): Promise<void> {
- const { olmAPI, sqliteAPI } = getConfig();
- if (message.type === peerToPeerMessageTypes.OUTBOUND_SESSION_CREATION) {
- const { senderInfo, encryptedData, sessionVersion } = message;
- const { userID: senderUserID, deviceID: senderDeviceID } = senderInfo;
-
- let deviceKeys: ?DeviceOlmInboundKeys = null;
- try {
- const { keys } = await identityClient.getInboundKeysForUser(senderUserID);
- deviceKeys = keys[senderDeviceID];
- } catch (e) {
- console.log(e.message);
- }
-
- if (!deviceKeys) {
- console.log(
- 'Error creating inbound session with device ' +
- `${senderDeviceID}: No keys for the device, ` +
- `session version: ${sessionVersion}`,
- );
- return;
- }
-
- try {
- await olmAPI.initializeCryptoAccount();
- const result = await olmAPI.contentInboundSessionCreator(
- deviceKeys.identityKeysBlob.primaryIdentityPublicKeys,
- encryptedData,
- sessionVersion,
- false,
- );
- console.log(
- 'Created inbound session with device ' +
- `${senderDeviceID}: ${result}, ` +
- `session version: ${sessionVersion}`,
- );
- } catch (e) {
- if (e.message?.includes(olmSessionErrors.alreadyCreated)) {
- console.log(
- 'Received session request with lower session version from ' +
- `${senderDeviceID}, session version: ${sessionVersion}`,
- );
- } else if (e.message?.includes(olmSessionErrors.raceCondition)) {
- const currentDeviceID = await getContentSigningKey();
- if (hasHigherDeviceID(currentDeviceID, senderDeviceID)) {
- console.log(
- 'Race condition while creating session with ' +
- `${senderDeviceID}, session version: ${sessionVersion}, ` +
- `this device has a higher deviceID and the session will be kept`,
- );
- } else {
- const result = await olmAPI.contentInboundSessionCreator(
- deviceKeys.identityKeysBlob.primaryIdentityPublicKeys,
- encryptedData,
- sessionVersion,
- true,
- );
- console.log(
- 'Overwrite session with device ' +
- `${senderDeviceID}: ${result}, ` +
- `session version: ${sessionVersion}`,
- );
- // Resend all not-yet confirmed messages that were encrypted
- // with overwrite session. Tracked in ENG-6982.
- }
- } else {
- console.log(
- 'Error creating inbound session with device ' +
- `${senderDeviceID}: ${e.message}, ` +
- `session version: ${sessionVersion}`,
- );
- }
- }
- } else if (message.type === peerToPeerMessageTypes.ENCRYPTED_MESSAGE) {
- try {
- await olmAPI.initializeCryptoAccount();
- const decrypted = await olmAPI.decryptSequentialAndPersist(
- message.encryptedData,
- message.senderInfo.deviceID,
- messageID,
- );
- console.log(
- 'Decrypted message from device ' +
- `${message.senderInfo.deviceID}: ${decrypted}`,
- );
-
- try {
- const parsedMessageToDevice = JSON.parse(decrypted);
- if (
- !secondaryDeviceLogoutP2PMessageValidator.is(parsedMessageToDevice)
- ) {
- return;
- }
- const { userID, deviceID: deviceIDToLogOut } = message.senderInfo;
- await removeDeviceFromDeviceList(
- identityClient,
- userID,
- deviceIDToLogOut,
- );
- // TODO: broadcast device list update here
- } catch (e) {
- console.log(e);
- }
- } catch (e) {
- if (e.message?.includes(olmSessionErrors.messageAlreadyDecrypted)) {
- console.log(
- 'Received already decrypted message from device ' +
- `${message.senderInfo.deviceID}.`,
- );
- } else if (e.message?.includes(olmSessionErrors.messageOutOfOrder)) {
- console.log(
- 'Received out-of-order message from device ' +
- `${message.senderInfo.deviceID}.`,
- );
- } else {
- console.log(
- 'Error decrypting message from device ' +
- `${message.senderInfo.deviceID}: ${e.message}`,
- );
- }
- }
- } else if (message.type === peerToPeerMessageTypes.REFRESH_KEY_REQUEST) {
- try {
- await olmAPI.initializeCryptoAccount();
- const oneTimeKeys = await olmAPI.getOneTimeKeys(message.numberOfKeys);
- await identityClient.uploadOneTimeKeys(oneTimeKeys);
- } catch (e) {
- console.log(`Error uploading one-time keys: ${e.message}`);
- }
- } else if (message.type === peerToPeerMessageTypes.DEVICE_LIST_UPDATED) {
- try {
- const result = await verifyAndGetDeviceList(
- identityClient,
- message.userID,
- null,
- );
- if (!result.valid) {
- console.log(
- `Received invalid device list update for user ${message.userID}. Reason: ${result.reason}`,
- );
- return;
- }
- console.log(
- `Received valid device list update for user ${message.userID}`,
- );
-
- if (message?.signedDeviceList?.rawDeviceList) {
- const receivedRawList = JSON.parse(
- message.signedDeviceList.rawDeviceList,
- );
-
- // additional check for broadcasted and Identity device list equality
- const listsAreEqual = _isEqual(result.deviceList)(receivedRawList);
- console.log(
- `Identity and received device lists are ${
- listsAreEqual ? '' : 'not'
- } equal.`,
- );
- }
- } catch (e) {
- console.log(
- `Error verifying device list for user ${message.userID}: ${e}`,
- );
- }
- } else if (message.type === peerToPeerMessageTypes.MESSAGE_PROCESSED) {
- try {
- const { deviceID, messageID: tunnelbrokerMessageID } = message;
- const clientMessageID = getClientMessageIDFromTunnelbrokerMessageID(
- tunnelbrokerMessageID,
- );
- await sqliteAPI.removeOutboundP2PMessagesOlderThan(
- clientMessageID,
- deviceID,
- );
- } catch (e) {
- console.log(
- `Error removing message after processing: ${
- getMessageForException(e) ?? 'unknown error'
- }`,
- );
- }
- }
-}
-
-export { peerToPeerMessageHandler };
diff --git a/lib/tunnelbroker/peer-to-peer-message-handler.js b/lib/tunnelbroker/peer-to-peer-message-handler.js
--- a/lib/tunnelbroker/peer-to-peer-message-handler.js
+++ b/lib/tunnelbroker/peer-to-peer-message-handler.js
@@ -1,11 +1,9 @@
// @flow
-import invariant from 'invariant';
import * as React from 'react';
import { useTunnelbroker } from './tunnelbroker-context.js';
-import { peerToPeerMessageHandler } from '../handlers/peer-to-peer-message-handler.js';
-import { IdentityClientContext } from '../shared/identity-client-context.js';
+import { usePeerToPeerMessageHandler } from './use-peer-to-peer-message-handler.js';
import type { MessageReceiveConfirmation } from '../types/tunnelbroker/message-receive-confirmation-types.js';
import {
tunnelbrokerMessageTypes,
@@ -25,10 +23,7 @@
const { socketSend, getSessionCounter, doesSocketExist } = props;
const { addListener, removeListener } = useTunnelbroker();
-
- const identityContext = React.useContext(IdentityClientContext);
- invariant(identityContext, 'Identity context should be set');
- const { identityClient } = identityContext;
+ const peerToPeerMessageHandler = usePeerToPeerMessageHandler();
const currentlyProcessedMessage = React.useRef<?Promise<mixed>>(null);
@@ -79,11 +74,7 @@
return;
}
try {
- await peerToPeerMessageHandler(
- peerToPeerMessage,
- identityClient,
- message.messageID,
- );
+ await peerToPeerMessageHandler(peerToPeerMessage, message.messageID);
} catch (e) {
console.log(e.message);
} finally {
@@ -97,7 +88,7 @@
}
})();
},
- [getSessionCounter, identityClient, doesSocketExist, socketSend],
+ [getSessionCounter, peerToPeerMessageHandler, doesSocketExist, socketSend],
);
React.useEffect(() => {
diff --git a/lib/tunnelbroker/use-peer-to-peer-message-handler.js b/lib/tunnelbroker/use-peer-to-peer-message-handler.js
new file mode 100644
--- /dev/null
+++ b/lib/tunnelbroker/use-peer-to-peer-message-handler.js
@@ -0,0 +1,225 @@
+// @flow
+
+import invariant from 'invariant';
+import _isEqual from 'lodash/fp/isEqual.js';
+import * as React from 'react';
+
+import {
+ verifyAndGetDeviceList,
+ removeDeviceFromDeviceList,
+} from '../shared/device-list-utils.js';
+import { IdentityClientContext } from '../shared/identity-client-context.js';
+import type { DeviceOlmInboundKeys } from '../types/identity-service-types.js';
+import {
+ peerToPeerMessageTypes,
+ type PeerToPeerMessage,
+} from '../types/tunnelbroker/peer-to-peer-message-types.js';
+import { secondaryDeviceLogoutP2PMessageValidator } from '../types/tunnelbroker/user-actions-peer-to-peer-message-types.js';
+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 { getClientMessageIDFromTunnelbrokerMessageID } from '../utils/peer-to-peer-communication-utils.js';
+
+function usePeerToPeerMessageHandler(): (
+ message: PeerToPeerMessage,
+ messageID: string,
+) => Promise<void> {
+ const { olmAPI, sqliteAPI } = getConfig();
+
+ const identityContext = React.useContext(IdentityClientContext);
+ invariant(identityContext, 'Identity context should be set');
+ const { identityClient } = identityContext;
+
+ return React.useCallback(
+ async (message: PeerToPeerMessage, messageID: string) => {
+ if (message.type === peerToPeerMessageTypes.OUTBOUND_SESSION_CREATION) {
+ const { senderInfo, encryptedData, sessionVersion } = message;
+ const { userID: senderUserID, deviceID: senderDeviceID } = senderInfo;
+
+ let deviceKeys: ?DeviceOlmInboundKeys = null;
+ try {
+ const { keys } =
+ await identityClient.getInboundKeysForUser(senderUserID);
+ deviceKeys = keys[senderDeviceID];
+ } catch (e) {
+ console.log(e.message);
+ }
+
+ if (!deviceKeys) {
+ console.log(
+ 'Error creating inbound session with device ' +
+ `${senderDeviceID}: No keys for the device, ` +
+ `session version: ${sessionVersion}`,
+ );
+ return;
+ }
+
+ try {
+ await olmAPI.initializeCryptoAccount();
+ const result = await olmAPI.contentInboundSessionCreator(
+ deviceKeys.identityKeysBlob.primaryIdentityPublicKeys,
+ encryptedData,
+ sessionVersion,
+ false,
+ );
+ console.log(
+ 'Created inbound session with device ' +
+ `${senderDeviceID}: ${result}, ` +
+ `session version: ${sessionVersion}`,
+ );
+ } catch (e) {
+ if (e.message?.includes(olmSessionErrors.alreadyCreated)) {
+ console.log(
+ 'Received session request with lower session version from ' +
+ `${senderDeviceID}, session version: ${sessionVersion}`,
+ );
+ } else if (e.message?.includes(olmSessionErrors.raceCondition)) {
+ const currentDeviceID = await getContentSigningKey();
+ if (hasHigherDeviceID(currentDeviceID, senderDeviceID)) {
+ console.log(
+ 'Race condition while creating session with ' +
+ `${senderDeviceID}, session version: ${sessionVersion}, ` +
+ `this device has a higher deviceID and the session will be kept`,
+ );
+ } else {
+ const result = await olmAPI.contentInboundSessionCreator(
+ deviceKeys.identityKeysBlob.primaryIdentityPublicKeys,
+ encryptedData,
+ sessionVersion,
+ true,
+ );
+ console.log(
+ 'Overwrite session with device ' +
+ `${senderDeviceID}: ${result}, ` +
+ `session version: ${sessionVersion}`,
+ );
+ // Resend all not-yet confirmed messages that were encrypted
+ // with overwrite session. Tracked in ENG-6982.
+ }
+ } else {
+ console.log(
+ 'Error creating inbound session with device ' +
+ `${senderDeviceID}: ${e.message}, ` +
+ `session version: ${sessionVersion}`,
+ );
+ }
+ }
+ } else if (message.type === peerToPeerMessageTypes.ENCRYPTED_MESSAGE) {
+ try {
+ await olmAPI.initializeCryptoAccount();
+ const decrypted = await olmAPI.decryptSequentialAndPersist(
+ message.encryptedData,
+ message.senderInfo.deviceID,
+ messageID,
+ );
+ console.log(
+ 'Decrypted message from device ' +
+ `${message.senderInfo.deviceID}: ${decrypted}`,
+ );
+
+ try {
+ const parsedMessageToDevice = JSON.parse(decrypted);
+ if (
+ !secondaryDeviceLogoutP2PMessageValidator.is(
+ parsedMessageToDevice,
+ )
+ ) {
+ return;
+ }
+ const { userID, deviceID: deviceIDToLogOut } = message.senderInfo;
+ await removeDeviceFromDeviceList(
+ identityClient,
+ userID,
+ deviceIDToLogOut,
+ );
+ // TODO: broadcast device list update here
+ } catch (e) {
+ console.log(e);
+ }
+ } catch (e) {
+ if (e.message?.includes(olmSessionErrors.messageAlreadyDecrypted)) {
+ console.log(
+ 'Received already decrypted message from device ' +
+ `${message.senderInfo.deviceID}.`,
+ );
+ } else if (e.message?.includes(olmSessionErrors.messageOutOfOrder)) {
+ console.log(
+ 'Received out-of-order message from device ' +
+ `${message.senderInfo.deviceID}.`,
+ );
+ } else {
+ console.log(
+ 'Error decrypting message from device ' +
+ `${message.senderInfo.deviceID}: ${e.message}`,
+ );
+ }
+ }
+ } else if (message.type === peerToPeerMessageTypes.REFRESH_KEY_REQUEST) {
+ try {
+ await olmAPI.initializeCryptoAccount();
+ const oneTimeKeys = await olmAPI.getOneTimeKeys(message.numberOfKeys);
+ await identityClient.uploadOneTimeKeys(oneTimeKeys);
+ } catch (e) {
+ console.log(`Error uploading one-time keys: ${e.message}`);
+ }
+ } else if (message.type === peerToPeerMessageTypes.DEVICE_LIST_UPDATED) {
+ try {
+ const result = await verifyAndGetDeviceList(
+ identityClient,
+ message.userID,
+ null,
+ );
+ if (!result.valid) {
+ console.log(
+ `Received invalid device list update for user ${message.userID}. Reason: ${result.reason}`,
+ );
+ return;
+ }
+ console.log(
+ `Received valid device list update for user ${message.userID}`,
+ );
+
+ if (message?.signedDeviceList?.rawDeviceList) {
+ const receivedRawList = JSON.parse(
+ message.signedDeviceList.rawDeviceList,
+ );
+
+ // additional check for broadcasted and Identity device
+ // list equality
+ const listsAreEqual = _isEqual(result.deviceList)(receivedRawList);
+ console.log(
+ `Identity and received device lists are ${
+ listsAreEqual ? '' : 'not'
+ } equal.`,
+ );
+ }
+ } catch (e) {
+ console.log(
+ `Error verifying device list for user ${message.userID}: ${e}`,
+ );
+ }
+ } else if (message.type === peerToPeerMessageTypes.MESSAGE_PROCESSED) {
+ try {
+ const { deviceID, messageID: tunnelbrokerMessageID } = message;
+ const clientMessageID = getClientMessageIDFromTunnelbrokerMessageID(
+ tunnelbrokerMessageID,
+ );
+ await sqliteAPI.removeOutboundP2PMessagesOlderThan(
+ clientMessageID,
+ deviceID,
+ );
+ } catch (e) {
+ console.log(
+ `Error removing message after processing: ${
+ getMessageForException(e) ?? 'unknown error'
+ }`,
+ );
+ }
+ }
+ },
+ [identityClient, olmAPI, sqliteAPI],
+ );
+}
+
+export { usePeerToPeerMessageHandler };
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Nov 29, 7:42 AM (16 h, 53 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2596343
Default Alt Text
D12372.diff (18 KB)
Attached To
Mode
D12372: [lib] convert `peerToPeerMessageHandler` to a hook
Attached
Detach File
Event Timeline
Log In to Comment