diff --git a/native/handlers/peer-to-peer-message-handler.js b/native/handlers/peer-to-peer-message-handler.js index 32653925b..391fed682 100644 --- a/native/handlers/peer-to-peer-message-handler.js +++ b/native/handlers/peer-to-peer-message-handler.js @@ -1,31 +1,46 @@ // @flow import { type PeerToPeerMessage, peerToPeerMessageTypes, } from 'lib/types/tunnelbroker/peer-to-peer-message-types.js'; +import { commCoreModule } from '../native-modules.js'; import { nativeInboundContentSessionCreator } from '../utils/crypto-utils.js'; async function peerToPeerMessageHandler( message: PeerToPeerMessage, ): Promise { if (message.type === peerToPeerMessageTypes.OUTBOUND_SESSION_CREATION) { try { const result = await nativeInboundContentSessionCreator(message); console.log( 'Created inbound session with device ' + `${message.senderInfo.deviceID}: ${result}`, ); } catch (e) { console.log( 'Error creating inbound session with device ' + `${message.senderInfo.deviceID}: ${e.message}`, ); } } else if (message.type === peerToPeerMessageTypes.ENCRYPTED_MESSAGE) { - console.log('Received encrypted message'); + try { + const decrypted = await commCoreModule.decrypt( + message.encryptedContent, + message.senderInfo.deviceID, + ); + console.log( + 'Decrypted message from device ' + + `${message.senderInfo.deviceID}: ${decrypted}`, + ); + } catch (e) { + console.log( + 'Error decrypting message from device ' + + `${message.senderInfo.deviceID}: ${e.message}`, + ); + } } } export { peerToPeerMessageHandler }; diff --git a/native/profile/tunnelbroker-menu.react.js b/native/profile/tunnelbroker-menu.react.js index 72550bd15..0719c4018 100644 --- a/native/profile/tunnelbroker-menu.react.js +++ b/native/profile/tunnelbroker-menu.react.js @@ -1,176 +1,226 @@ // @flow import * as React from 'react'; import { useState } from 'react'; import { Text, View } from 'react-native'; import { ScrollView } from 'react-native-gesture-handler'; import { useTunnelbroker } from 'lib/tunnelbroker/tunnelbroker-context.js'; import type { TunnelbrokerMessage } from 'lib/types/tunnelbroker/messages.js'; +import { + type EncryptedMessage, + peerToPeerMessageTypes, +} from 'lib/types/tunnelbroker/peer-to-peer-message-types.js'; import type { ProfileNavigationProp } from './profile.react.js'; import Button from '../components/button.react.js'; import TextInput from '../components/text-input.react.js'; +import { commCoreModule } from '../native-modules.js'; import type { NavigationRoute } from '../navigation/route-names.js'; +import { useSelector } from '../redux/redux-utils.js'; import { useColors, useStyles } from '../themes/colors.js'; -import { createOlmSessionsWithOwnDevices } from '../utils/crypto-utils.js'; +import { + createOlmSessionsWithOwnDevices, + getContentSigningKey, +} from '../utils/crypto-utils.js'; type Props = { +navigation: ProfileNavigationProp<'TunnelbrokerMenu'>, +route: NavigationRoute<'TunnelbrokerMenu'>, }; // eslint-disable-next-line no-unused-vars function TunnelbrokerMenu(props: Props): React.Node { const styles = useStyles(unboundStyles); const colors = useColors(); + const currentUserID = useSelector( + state => state.currentUserInfo && state.currentUserInfo.id, + ); const { connected, addListener, sendMessage, removeListener } = useTunnelbroker(); const [messages, setMessages] = useState([]); const [recipient, setRecipient] = useState(''); const [message, setMessage] = useState(''); const listener = React.useCallback((msg: TunnelbrokerMessage) => { setMessages(prev => [...prev, msg]); }, []); React.useEffect(() => { addListener(listener); return () => removeListener(listener); }, [addListener, listener, removeListener]); const onSubmit = React.useCallback(async () => { try { await sendMessage({ deviceID: recipient, payload: message }); } catch (e) { console.log(e.message); } }, [message, recipient, sendMessage]); const onCreateSessions = React.useCallback(async () => { try { await createOlmSessionsWithOwnDevices(sendMessage); } catch (e) { console.log(`Error creating olm sessions with own devices: ${e.message}`); } }, [sendMessage]); + const onSendEncryptedMessage = React.useCallback(async () => { + try { + if (!currentUserID) { + return; + } + const encrypted = await commCoreModule.encrypt( + `Encrypted message to ${recipient}`, + recipient, + ); + const deviceID = await getContentSigningKey(); + const encryptedMessage: EncryptedMessage = { + type: peerToPeerMessageTypes.ENCRYPTED_MESSAGE, + senderInfo: { + deviceID, + userID: currentUserID, + }, + encryptedContent: encrypted, + }; + await sendMessage({ + deviceID: recipient, + payload: JSON.stringify(encryptedMessage), + }); + } catch (e) { + console.log(`Error sending encrypted content to device: ${e.message}`); + } + }, [currentUserID, recipient, sendMessage]); + return ( INFO Connected {connected.toString()} SEND MESSAGE Recipient Message + MESSAGES {messages.map(msg => ( {JSON.stringify(msg)} ))} ); } const unboundStyles = { scrollViewContentContainer: { paddingTop: 24, }, scrollView: { backgroundColor: 'panelBackground', }, section: { backgroundColor: 'panelForeground', borderBottomWidth: 1, borderColor: 'panelForegroundBorder', borderTopWidth: 1, marginBottom: 24, marginVertical: 2, }, header: { color: 'panelBackgroundLabel', fontSize: 12, fontWeight: '400', paddingBottom: 3, paddingHorizontal: 24, }, submenuButton: { flexDirection: 'row', paddingHorizontal: 24, paddingVertical: 10, alignItems: 'center', }, submenuText: { color: 'panelForegroundLabel', flex: 1, fontSize: 16, }, text: { color: 'panelForegroundLabel', fontSize: 16, }, row: { flexDirection: 'row', justifyContent: 'space-between', paddingHorizontal: 24, paddingVertical: 14, }, textInput: { color: 'modalBackgroundLabel', flex: 1, fontSize: 16, margin: 0, padding: 0, borderBottomColor: 'transparent', }, }; export default TunnelbrokerMenu;