diff --git a/examples_dart/bin/omemo_client.dart b/examples_dart/bin/omemo_client.dart index 183f999..2aef2fd 100644 --- a/examples_dart/bin/omemo_client.dart +++ b/examples_dart/bin/omemo_client.dart @@ -6,24 +6,6 @@ import 'package:moxxmpp/moxxmpp.dart'; import 'package:moxxmpp_socket_tcp/moxxmpp_socket_tcp.dart'; import 'package:omemo_dart/omemo_dart.dart' as omemo; -class TestingOmemoManager extends BaseOmemoManager { - TestingOmemoManager(this._encryptToJid); - - final JID _encryptToJid; - - late omemo.OmemoManager manager; - - @override - Future getOmemoManager() async { - return manager; - } - - @override - Future shouldEncryptStanza(JID toJid, Stanza stanza) async { - return toJid.toBare() == _encryptToJid; - } -} - class TestingTCPSocketWrapper extends TCPSocketWrapper { @override bool onBadCertificate(dynamic certificate, String domain) { @@ -66,17 +48,21 @@ void main(List args) async { ); // Generate OMEMO data - final moxxmppOmemo = TestingOmemoManager(to); - final omemoManager = omemo.OmemoManager( + omemo.OmemoManager? oom; + final moxxmppOmemo = OmemoManager( + () async => oom!, + (toJid, _) async => toJid == to, + ); + oom = omemo.OmemoManager( await omemo.OmemoDevice.generateNewDevice(jid.toString(), opkAmount: 5), omemo.BlindTrustBeforeVerificationTrustManager(), moxxmppOmemo.sendEmptyMessageImpl, moxxmppOmemo.fetchDeviceList, moxxmppOmemo.fetchDeviceBundle, moxxmppOmemo.subscribeToDeviceListImpl, + moxxmppOmemo.publishDeviceImpl, ); - moxxmppOmemo.manager = omemoManager; - final deviceId = await omemoManager.getDeviceId(); + final deviceId = await oom.getDeviceId(); Logger.root.info('Our device id: $deviceId'); // Register the managers and negotiators @@ -85,7 +71,7 @@ void main(List args) async { DiscoManager([]), PubSubManager(), MessageManager(), - moxxmppOmemo, + moxxmppOmemo, ]); await connection.registerFeatureNegotiators([ SaslPlainNegotiator(), @@ -118,7 +104,7 @@ void main(List args) async { // Publish our bundle Logger.root.info('Publishing bundle'); - final device = await moxxmppOmemo.manager.getDevice(); + final device = await oom.getDevice(); final omemoResult = await moxxmppOmemo.publishBundle(await device.toBundle()); if (!omemoResult.isType()) { Logger.root.severe('Failed to publish OMEMO bundle: ${omemoResult.get()}'); diff --git a/packages/moxxmpp/lib/src/xeps/xep_0384/xep_0384.dart b/packages/moxxmpp/lib/src/xeps/xep_0384/xep_0384.dart index bf3fc07..2ea82c3 100644 --- a/packages/moxxmpp/lib/src/xeps/xep_0384/xep_0384.dart +++ b/packages/moxxmpp/lib/src/xeps/xep_0384/xep_0384.dart @@ -26,6 +26,18 @@ import 'package:moxxmpp/src/xeps/xep_0384/types.dart'; import 'package:omemo_dart/omemo_dart.dart' as omemo; import 'package:xml/xml.dart'; +/// A callback that is executed whenever we need to acquire the OmemoManager backing +/// the manager. +typedef GetOmemoManagerCallback = Future Function(); + +/// A callback for figuring out whether a stanza should be encrypted or not. Note that +/// returning true here does not necessarily mean that a stanza gets encrypted because +/// handlers can indicate that a stanza should not be encrypted, e.g. PubSub. +typedef ShouldEncryptStanzaCallback = Future Function( + JID toJid, + Stanza stanza, +); + const _doNotEncryptList = [ // XEP-0033 DoNotEncrypt('addresses', extendedAddressingXmlns), @@ -42,8 +54,15 @@ const _doNotEncryptList = [ DoNotEncrypt('stanza-id', stableIdXmlns), ]; -abstract class BaseOmemoManager extends XmppManagerBase { - BaseOmemoManager() : super(omemoManager); +class OmemoManager extends XmppManagerBase { + OmemoManager(this._getOmemoManager, this._shouldEncryptStanza) + : super(omemoManager); + + /// Callback for getting the [omemo.OmemoManager]. + final GetOmemoManagerCallback _getOmemoManager; + + /// Callback for checking whether a stanza should be encrypted or not. + final ShouldEncryptStanzaCallback _shouldEncryptStanza; // TODO(Unknown): Technically, this is not always true @override @@ -112,22 +131,19 @@ abstract class BaseOmemoManager extends XmppManagerBase { } // Tell the OmemoManager - await (await getOmemoManager()).onDeviceListUpdate(jid.toString(), ids); + await (await _getOmemoManager()).onDeviceListUpdate(jid.toString(), ids); // Generate an event getAttributes().sendEvent(OmemoDeviceListUpdatedEvent(jid, ids)); } } - @visibleForOverriding - Future getOmemoManager(); - /// Wrapper around using getSessionManager and then calling getDeviceId on it. - Future _getDeviceId() async => (await getOmemoManager()).getDeviceId(); + Future _getDeviceId() async => (await _getOmemoManager()).getDeviceId(); /// Wrapper around using getSessionManager and then calling getDeviceId on it. Future _getDeviceBundle() async { - final om = await getOmemoManager(); + final om = await _getOmemoManager(); final device = await om.getDevice(); return device.toBundle(); } @@ -279,7 +295,7 @@ abstract class BaseOmemoManager extends XmppManagerBase { /// Send a heartbeat message to [jid]. Future sendOmemoHeartbeat(String jid) async { - final om = await getOmemoManager(); + final om = await _getOmemoManager(); await om.sendOmemoHeartbeat(jid); } @@ -320,7 +336,7 @@ abstract class BaseOmemoManager extends XmppManagerBase { } final toJid = JID.fromString(stanza.to!).toBare(); - final shouldEncryptResult = await shouldEncryptStanza(toJid, stanza); + final shouldEncryptResult = await _shouldEncryptStanza(toJid, stanza); if (!shouldEncryptResult && !state.forceEncryption) { logger.finest( 'Not encrypting stanza for $toJid: Both shouldEncryptStanza and forceEncryption are false.', @@ -347,7 +363,7 @@ abstract class BaseOmemoManager extends XmppManagerBase { .getManagerById(carbonsManager) ?.isEnabled ?? false; - final om = await getOmemoManager(); + final om = await _getOmemoManager(); final encryptToJids = [ toJid.toString(), if (carbonsEnabled) getAttributes().getFullJID().toBare().toString(), @@ -397,12 +413,6 @@ abstract class BaseOmemoManager extends XmppManagerBase { ..encrypted = true; } - /// This function is called whenever a message is to be encrypted. If it returns true, - /// then the message will be encrypted. If it returns false, the message won't be - /// encrypted. - @visibleForOverriding - Future shouldEncryptStanza(JID toJid, Stanza stanza); - Future _onIncomingStanza( Stanza stanza, StanzaHandlerData state, @@ -434,7 +444,7 @@ abstract class BaseOmemoManager extends XmppManagerBase { } final sid = int.parse(header.attributes['sid']! as String); - final om = await getOmemoManager(); + final om = await _getOmemoManager(); final result = await om.onIncomingStanza( omemo.OmemoIncomingStanza( fromJid.toString(), @@ -644,6 +654,11 @@ abstract class BaseOmemoManager extends XmppManagerBase { await pm.subscribe(JID.fromString(jid), omemoDevicesXmlns); } + /// Implementation for publishing our device [device]. + Future publishDeviceImpl(omemo.OmemoDevice device) async { + await publishBundle(await device.toBundle()); + } + /// Attempts to find out if [jid] supports omemo:2. /// /// On success, returns whether [jid] has published a device list and device bundles.