From cdd26c915d6ca80dd7d69079cce34e865f85e1fd Mon Sep 17 00:00:00 2001 From: COM8 Date: Thu, 14 Mar 2019 16:28:48 +0100 Subject: [PATCH] Switched all the OMEMO stuff to the AsyncMessageResponseHelper --- .../Classes/Crypto/Omemo/Test_Omemo.cs | 4 +- Data_Manager2/Classes/ConnectionHandler.cs | 8 +- .../Classes/DBManager/DiscoDBManager.cs | 2 +- .../OMEMO/OmemoDeviceListControl.xaml.cs | 8 +- .../Classes/AppBackgroundHelper.cs | 6 +- .../Controls/ChatDetailsControlContext.cs | 2 +- .../Controls/OmemoDeviceListControlContext.cs | 47 +-- XMPP_API/Classes/GeneralCommandHelper.cs | 47 +-- XMPP_API/Classes/MUCCommandHelper.cs | 39 +-- XMPP_API/Classes/Network/OmemoHelper.cs | 316 +++++------------- .../Classes/Network/StreamManagementHelper.cs | 14 +- .../Helper/AsyncMessageResponseHelper.cs | 7 +- .../Messages/XEP-0384/OmemoMessageMessage.cs | 13 +- .../Signal/Session/OmemoSessionBuildHelper.cs | 289 +++++++--------- XMPP_API/Classes/Network/XMPPConnection2.cs | 10 + XMPP_API/Classes/OmemoCommandHelper.cs | 97 ++++-- XMPP_API/Classes/PubSubCommandHelper.cs | 65 ++-- XMPP_API/Classes/XMPPClient.cs | 18 +- 18 files changed, 428 insertions(+), 564 deletions(-) diff --git a/Component_Tests/Classes/Crypto/Omemo/Test_Omemo.cs b/Component_Tests/Classes/Crypto/Omemo/Test_Omemo.cs index a0631a759..c36632d2c 100644 --- a/Component_Tests/Classes/Crypto/Omemo/Test_Omemo.cs +++ b/Component_Tests/Classes/Crypto/Omemo/Test_Omemo.cs @@ -158,7 +158,7 @@ public void Test_Omemo_Enc_Dec_1() [TestCategory("Crypto")] [TestMethod] - public void Test_Omemo_Enc_Dec_2() + public async void Test_Omemo_Enc_Dec_2() { // Generate Alices keys: IdentityKeyPair aliceIdentKey = CryptoUtils.generateOmemoIdentityKeyPair(); @@ -249,7 +249,7 @@ public void Test_Omemo_Enc_Dec_2() // Bob decrypts the message: SignalProtocolAddress aliceAddress = new SignalProtocolAddress(Utils.getBareJidFromFullJid(bobOmemoMessage.getFrom()), bobOmemoMessage.SOURCE_DEVICE_ID); SessionCipher bobSessionCipher = new SessionCipher(bobSessionStore, bobPreKeyStore, bobSignedPreKeyStore, bobIdentStore, aliceAddress); - bobOmemoMessage.decrypt(bobSessionCipher, aliceAddress, BOB_ADDRESS.getDeviceId(), null); + await bobOmemoMessage.decryptAsync(bobSessionCipher, aliceAddress, BOB_ADDRESS.getDeviceId(), null); Assert.IsFalse(bobOmemoMessage.ENCRYPTED); Assert.AreEqual(aliceOrigMsg, bobOmemoMessage.MESSAGE); } diff --git a/Data_Manager2/Classes/ConnectionHandler.cs b/Data_Manager2/Classes/ConnectionHandler.cs index 36498196f..a2e1b9e39 100644 --- a/Data_Manager2/Classes/ConnectionHandler.cs +++ b/Data_Manager2/Classes/ConnectionHandler.cs @@ -487,7 +487,7 @@ private void C_NewRoosterMessage(IMessageSender sender, NewValidMessageEventArgs } } - private void C_NewChatMessage(XMPPClient client, XMPP_API.Classes.Network.Events.NewChatMessageEventArgs args) + private async void C_NewChatMessage(XMPPClient client, XMPP_API.Classes.Network.Events.NewChatMessageEventArgs args) { MessageMessage msg = args.getMessage(); @@ -526,7 +526,7 @@ private void C_NewChatMessage(XMPPClient client, XMPP_API.Classes.Network.Events Logger.Error("Failed to decrypt OMEMO message - keys are corrupted"); return; } - else if (!omemoMessage.decrypt(client.getOmemoHelper(), client.getXMPPAccount().omemoDeviceId)) + else if (!await omemoMessage.decryptAsync(client.getOmemoHelper(), client.getXMPPAccount().omemoDeviceId)) { return; } @@ -622,7 +622,7 @@ private void C_NewChatMessage(XMPPClient client, XMPP_API.Classes.Network.Events // Send XEP-0184 (Message Delivery Receipts) reply: if (msg.RECIPT_REQUESTED && id != null && !Settings.getSettingBoolean(SettingsConsts.DONT_SEND_CHAT_MESSAGE_RECEIVED_MARKERS)) { - Task.Run(async () => + await Task.Run(async () => { DeliveryReceiptMessage receiptMessage = new DeliveryReceiptMessage(client.getXMPPAccount().getFullJid(), from, msg.ID); await client.sendAsync(receiptMessage, true); @@ -634,7 +634,7 @@ private void C_NewChatMessage(XMPPClient client, XMPP_API.Classes.Network.Events // Show toast: if (!doesMessageExist && !chat.muted) { - Task.Run(() => + await Task.Run(() => { try { diff --git a/Data_Manager2/Classes/DBManager/DiscoDBManager.cs b/Data_Manager2/Classes/DBManager/DiscoDBManager.cs index 5182fa88b..14461d682 100644 --- a/Data_Manager2/Classes/DBManager/DiscoDBManager.cs +++ b/Data_Manager2/Classes/DBManager/DiscoDBManager.cs @@ -162,7 +162,7 @@ protected override void dropTables() #endregion //--------------------------------------------------------Events:---------------------------------------------------------------------\\ #region --Events-- - private async void INSTANCE_ClientConnected(ConnectionHandler handler, Events.ClientConnectedEventArgs args) + private void INSTANCE_ClientConnected(ConnectionHandler handler, Events.ClientConnectedEventArgs args) { //messageIdCache.addTimed(await args.CLIENT.createDiscoAsync(args.CLIENT.getXMPPAccount().user.domain, DiscoType.ITEMS)); //messageIdCache.addTimed(await args.CLIENT.createDiscoAsync(args.CLIENT.getXMPPAccount().user.domain, DiscoType.INFO)); diff --git a/UWPX_UI/Controls/OMEMO/OmemoDeviceListControl.xaml.cs b/UWPX_UI/Controls/OMEMO/OmemoDeviceListControl.xaml.cs index f76b8dc84..9757dc037 100644 --- a/UWPX_UI/Controls/OMEMO/OmemoDeviceListControl.xaml.cs +++ b/UWPX_UI/Controls/OMEMO/OmemoDeviceListControl.xaml.cs @@ -52,14 +52,14 @@ private void UpdateView(DependencyPropertyChangedEventArgs e) #endregion //--------------------------------------------------------Events:---------------------------------------------------------------------\\ #region --Events-- - private void Reset_ibtn_Click(object sender, RoutedEventArgs args) + private async void Reset_ibtn_Click(object sender, RoutedEventArgs args) { - VIEW_MODEL.ResetOmemoDevices(Account.Client); + await VIEW_MODEL.ResetOmemoDevicesAsync(Account.Client); } - private void Refresh_ibtn_Click(object sender, RoutedEventArgs args) + private async void Refresh_ibtn_Click(object sender, RoutedEventArgs args) { - VIEW_MODEL.RefreshOmemoDevices(Account.Client); + await VIEW_MODEL.RefreshOmemoDevicesAsync(Account.Client); } private static void OnAccountChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) diff --git a/UWPX_UI_Context/Classes/AppBackgroundHelper.cs b/UWPX_UI_Context/Classes/AppBackgroundHelper.cs index b76f37d34..bac075c02 100644 --- a/UWPX_UI_Context/Classes/AppBackgroundHelper.cs +++ b/UWPX_UI_Context/Classes/AppBackgroundHelper.cs @@ -1,8 +1,4 @@ using Data_Manager2.Classes; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Threading.Tasks; namespace UWPX_UI_Context.Classes @@ -26,7 +22,9 @@ public static class AppBackgroundHelper #endregion //--------------------------------------------------------Misc Methods:---------------------------------------------------------------\\ #region --Misc Methods (Public)-- +#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously public static async Task InitAsync() +#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously { TrySetDefaultBackground(); } diff --git a/UWPX_UI_Context/Classes/DataContext/Controls/ChatDetailsControlContext.cs b/UWPX_UI_Context/Classes/DataContext/Controls/ChatDetailsControlContext.cs index 5909be18a..a66ebeb27 100644 --- a/UWPX_UI_Context/Classes/DataContext/Controls/ChatDetailsControlContext.cs +++ b/UWPX_UI_Context/Classes/DataContext/Controls/ChatDetailsControlContext.cs @@ -140,7 +140,7 @@ await Task.Run(() => // Send the message: if (toSendMsg is OmemoMessageMessage toSendOmemoMsg) { - chat.Client.sendOmemoMessage(toSendOmemoMsg, chat.Chat.chatJabberId, chat.Client.getXMPPAccount().getBareJid()); + await chat.Client.sendOmemoMessageAsync(toSendOmemoMsg, chat.Chat.chatJabberId, chat.Client.getXMPPAccount().getBareJid()); } else { diff --git a/UWPX_UI_Context/Classes/DataContext/Controls/OmemoDeviceListControlContext.cs b/UWPX_UI_Context/Classes/DataContext/Controls/OmemoDeviceListControlContext.cs index 1e70c175f..0c2d57125 100644 --- a/UWPX_UI_Context/Classes/DataContext/Controls/OmemoDeviceListControlContext.cs +++ b/UWPX_UI_Context/Classes/DataContext/Controls/OmemoDeviceListControlContext.cs @@ -1,9 +1,12 @@ -using System.Linq; +using Logging; +using System.Linq; +using System.Threading.Tasks; using UWPX_UI_Context.Classes.DataTemplates; using UWPX_UI_Context.Classes.DataTemplates.Controls; using Windows.UI.Xaml; using XMPP_API.Classes; -using XMPP_API.Classes.Network; +using XMPP_API.Classes.Network.XML.Messages; +using XMPP_API.Classes.Network.XML.Messages.Helper; using XMPP_API.Classes.Network.XML.Messages.XEP_0384; namespace UWPX_UI_Context.Classes.DataContext.Controls @@ -27,14 +30,13 @@ public sealed class OmemoDeviceListControlContext #endregion //--------------------------------------------------------Misc Methods:---------------------------------------------------------------\\ #region --Misc Methods (Public)-- - public void ResetOmemoDevices(XMPPClient client) + public async Task ResetOmemoDevicesAsync(XMPPClient client) { - OmemoHelper helper = client.getOmemoHelper(); - if (!MODEL.ResettingDevices && !(helper is null)) - { - MODEL.ResettingDevices = true; - helper.resetDeviceListStateless(OnResetDeviceListResult); - } + MODEL.ResettingDevices = true; + OmemoDevices devices = new OmemoDevices(); + devices.IDS.Add(client.getXMPPAccount().omemoDeviceId); + await client.OMEMO_COMMAND_HELPER.setDeviceListAsync(devices); + MODEL.ResettingDevices = false; } private void OnResetDeviceListResult(bool success) @@ -42,22 +44,27 @@ private void OnResetDeviceListResult(bool success) MODEL.ResettingDevices = false; } - public void RefreshOmemoDevices(XMPPClient client) + public async Task RefreshOmemoDevicesAsync(XMPPClient client) { - OmemoHelper helper = client.getOmemoHelper(); - if (!MODEL.RefreshingDevices && !(helper is null)) + MODEL.RefreshingDevices = true; + MessageResponseHelperResult result = await client.OMEMO_COMMAND_HELPER.requestDeviceListAsync(client.getXMPPAccount().getBareJid()); + if (result.STATE == MessageResponseHelperResultState.SUCCESS) { - helper.requestDeviceListStateless(OnRequestDeviceListResult); + if (result.RESULT is OmemoDeviceListResultMessage deviceListResultMessage) + { + MODEL.DEVICES.Clear(); + MODEL.DEVICES.AddRange(deviceListResultMessage.DEVICES.IDS.Select(x => new UintDataTemplate { Value = x })); + } + else + { + Logger.Warn("Failed to request device list (" + result.RESULT.ToString() + ")."); + } } - } - - private void OnRequestDeviceListResult(bool success, OmemoDevices devices) - { - if (success) + else { - MODEL.DEVICES.Clear(); - MODEL.DEVICES.AddRange(devices.IDS.Select(x => new UintDataTemplate { Value = x })); + Logger.Warn("Failed to request device list (" + result.STATE.ToString() + ")."); } + MODEL.RefreshingDevices = false; } public void UpdateView(DependencyPropertyChangedEventArgs e) diff --git a/XMPP_API/Classes/GeneralCommandHelper.cs b/XMPP_API/Classes/GeneralCommandHelper.cs index c4f27abad..b4a2e81ba 100644 --- a/XMPP_API/Classes/GeneralCommandHelper.cs +++ b/XMPP_API/Classes/GeneralCommandHelper.cs @@ -1,6 +1,7 @@ using Logging; using System; using System.Threading.Tasks; +using XMPP_API.Classes.Network; using XMPP_API.Classes.Network.XML.Messages; using XMPP_API.Classes.Network.XML.Messages.Helper; using XMPP_API.Classes.Network.XML.Messages.XEP_0030; @@ -12,7 +13,7 @@ public class GeneralCommandHelper { //--------------------------------------------------------Attributes:-----------------------------------------------------------------\\ #region --Attributes-- - private readonly XMPPClient CLIENT; + private readonly XMPPConnection2 CONNECTION; #endregion //--------------------------------------------------------Constructor:----------------------------------------------------------------\\ @@ -23,9 +24,9 @@ public class GeneralCommandHelper /// /// 02/11/2018 Created [Fabian Sauter] /// - public GeneralCommandHelper(XMPPClient client) + public GeneralCommandHelper(XMPPConnection2 connection) { - this.CLIENT = client; + this.CONNECTION = connection; } #endregion @@ -53,7 +54,7 @@ public async Task setPreseceAsync(Presence presence, string status) public async Task setPreseceAsync(string from, string to, Presence presence, string status) { PresenceMessage presenceMessage = new PresenceMessage(from, to, presence, status, int.MinValue); - await CLIENT.sendAsync(presenceMessage); + await CONNECTION.sendAsync(presenceMessage); return presenceMessage.ID; } @@ -67,8 +68,8 @@ public async Task setPreseceAsync(string from, string to, Presence prese public async Task> requestRosterAsync() { Predicate predicate = (x) => { return true; }; - AsyncMessageResponseHelper helper = new AsyncMessageResponseHelper(CLIENT, predicate); - RosterRequestMessage msg = new RosterRequestMessage(CLIENT.getXMPPAccount().getFullJid(), CLIENT.getXMPPAccount().getBareJid()); + AsyncMessageResponseHelper helper = new AsyncMessageResponseHelper(CONNECTION, predicate); + RosterRequestMessage msg = new RosterRequestMessage(CONNECTION.account.getFullJid(), CONNECTION.account.getBareJid()); return await helper.startAsync(msg); } @@ -78,8 +79,8 @@ public async Task> requestRosterAsync() /// True if sending the message succeeded. public async Task sendRequestRosterMessageAsync() { - RosterRequestMessage msg = new RosterRequestMessage(CLIENT.getXMPPAccount().getFullJid(), CLIENT.getXMPPAccount().getBareJid()); - return await CLIENT.sendAsync(msg); + RosterRequestMessage msg = new RosterRequestMessage(CONNECTION.account.getFullJid(), CONNECTION.account.getBareJid()); + return await CONNECTION.sendAsync(msg); } /// @@ -90,7 +91,7 @@ public async Task sendRequestRosterMessageAsync() public async Task sendPresenceProbeAsync(string fromFullJid, string toBareJid) { PresenceProbeMessage msg = new PresenceProbeMessage(fromFullJid, toBareJid); - await CLIENT.sendAsync(msg); + await CONNECTION.sendAsync(msg); Logger.Info("Send presence probe from " + fromFullJid + " to " + toBareJid); } @@ -102,8 +103,8 @@ public async Task sendPresenceProbeAsync(string fromFullJid, string toBareJid) /// The id of the send AddToRosterMessage. public async Task addToRosterAsync(string bareJid) { - AddToRosterMessage msg = new AddToRosterMessage(CLIENT.getXMPPAccount().getFullJid(), bareJid); - await CLIENT.sendAsync(msg, true); + AddToRosterMessage msg = new AddToRosterMessage(CONNECTION.account.getFullJid(), bareJid); + await CONNECTION.sendAsync(msg, true); return msg.ID; } @@ -115,8 +116,8 @@ public async Task addToRosterAsync(string bareJid) /// The id of the send RemoveFromRosterMessage. public async Task removeFromRosterAsync(string bareJid) { - RemoveFromRosterMessage msg = new RemoveFromRosterMessage(CLIENT.getXMPPAccount().getFullJid(), bareJid); - await CLIENT.sendAsync(msg, true); + RemoveFromRosterMessage msg = new RemoveFromRosterMessage(CONNECTION.account.getFullJid(), bareJid); + await CONNECTION.sendAsync(msg, true); return msg.ID; } @@ -127,8 +128,8 @@ public async Task removeFromRosterAsync(string bareJid) /// The chat state. public async Task sendChatStateAsync(string target, ChatState state) { - ChatStateMessage chatStateMessage = new ChatStateMessage(target, CLIENT.getXMPPAccount().getFullJid(), state); - await CLIENT.sendAsync(chatStateMessage); + ChatStateMessage chatStateMessage = new ChatStateMessage(target, CONNECTION.account.getFullJid(), state); + await CONNECTION.sendAsync(chatStateMessage); } /// @@ -141,8 +142,8 @@ public async Task sendChatStateAsync(string target, ChatState state) /// Returns a MessageResponseHelper listening for DiscoRequestMessage answers. public MessageResponseHelper createDisco(string target, DiscoType type, MessageResponseHelper.OnMessageHandler onMessage, MessageResponseHelper.OnTimeoutHandler onTimeout) { - MessageResponseHelper helper = new MessageResponseHelper(CLIENT, onMessage, onTimeout); - DiscoRequestMessage disco = new DiscoRequestMessage(CLIENT.getXMPPAccount().getFullJid(), target, type); + MessageResponseHelper helper = new MessageResponseHelper(CONNECTION, onMessage, onTimeout); + DiscoRequestMessage disco = new DiscoRequestMessage(CONNECTION.account.getFullJid(), target, type); helper.start(disco); return helper; } @@ -153,8 +154,8 @@ public MessageResponseHelper createDisco(string target, DiscoType typ /// The bare JID of the target e.g. 'witches@conference.jabber.org'. public async Task requestPresenceSubscriptionAsync(string bareJid) { - PresenceMessage msg = new PresenceMessage(CLIENT.getXMPPAccount().getBareJid(), bareJid, "subscribe"); - await CLIENT.sendAsync(msg, true); + PresenceMessage msg = new PresenceMessage(CONNECTION.account.getBareJid(), bareJid, "subscribe"); + await CONNECTION.sendAsync(msg, true); } /// @@ -163,8 +164,8 @@ public async Task requestPresenceSubscriptionAsync(string bareJid) /// The bare JID of the target e.g. 'witches@conference.jabber.org'. public async Task unsubscribeFromPresenceAsync(string bareJid) { - PresenceMessage msg = new PresenceMessage(CLIENT.getXMPPAccount().getBareJid(), bareJid, "unsubscribe"); - await CLIENT.sendAsync(msg, true); + PresenceMessage msg = new PresenceMessage(CONNECTION.account.getBareJid(), bareJid, "unsubscribe"); + await CONNECTION.sendAsync(msg, true); } /// @@ -174,8 +175,8 @@ public async Task unsubscribeFromPresenceAsync(string bareJid) /// Whether the request was accepted or not. public async Task answerPresenceSubscriptionRequestAsync(string bareJid, bool accept) { - PresenceMessage msg = new PresenceMessage(CLIENT.getXMPPAccount().getBareJid(), bareJid, accept ? "subscribed" : "unsubscribed"); - await CLIENT.sendAsync(msg, true); + PresenceMessage msg = new PresenceMessage(CONNECTION.account.getBareJid(), bareJid, accept ? "subscribed" : "unsubscribed"); + await CONNECTION.sendAsync(msg, true); } #endregion diff --git a/XMPP_API/Classes/MUCCommandHelper.cs b/XMPP_API/Classes/MUCCommandHelper.cs index 4856ccb6c..4e3e89a82 100644 --- a/XMPP_API/Classes/MUCCommandHelper.cs +++ b/XMPP_API/Classes/MUCCommandHelper.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using XMPP_API.Classes.Network; using XMPP_API.Classes.Network.XML.Messages; using XMPP_API.Classes.Network.XML.Messages.XEP_0004; using XMPP_API.Classes.Network.XML.Messages.XEP_0030; @@ -11,7 +12,7 @@ public class MUCCommandHelper { //--------------------------------------------------------Attributes:-----------------------------------------------------------------\\ #region --Attributes-- - private readonly XMPPClient CLIENT; + private readonly XMPPConnection2 CONNECTION; #endregion //--------------------------------------------------------Constructor:----------------------------------------------------------------\\ @@ -22,9 +23,9 @@ public class MUCCommandHelper /// /// 08/03/2018 Created [Fabian Sauter] /// - public MUCCommandHelper(XMPPClient client) + public MUCCommandHelper(XMPPConnection2 connection) { - this.CLIENT = client; + this.CONNECTION = connection; } #endregion @@ -44,7 +45,7 @@ public MUCCommandHelper(XMPPClient client) /// Returns a MessageResponseHelper listening for DiscoRequestMessage answers. public MessageResponseHelper requestRooms(string server, MessageResponseHelper.OnMessageHandler onMessage, MessageResponseHelper.OnTimeoutHandler onTimeout) { - return CLIENT.GENERAL_COMMAND_HELPER.createDisco(server, DiscoType.ITEMS, onMessage, onTimeout); + return CONNECTION.GENERAL_COMMAND_HELPER.createDisco(server, DiscoType.ITEMS, onMessage, onTimeout); } /// @@ -56,8 +57,8 @@ public MessageResponseHelper requestRooms(string server, MessageRespo /// Returns a MessageResponseHelper listening for DiscoRequestMessage answers. public MessageResponseHelper requestRoomInfo(string roomJid, MessageResponseHelper.OnMessageHandler onMessage, MessageResponseHelper.OnTimeoutHandler onTimeout) { - MessageResponseHelper helper = new MessageResponseHelper(CLIENT, onMessage, onTimeout); - DiscoRequestMessage disco = new DiscoRequestMessage(CLIENT.getXMPPAccount().getFullJid(), roomJid, DiscoType.INFO); + MessageResponseHelper helper = new MessageResponseHelper(CONNECTION, onMessage, onTimeout); + DiscoRequestMessage disco = new DiscoRequestMessage(CONNECTION.account.getFullJid(), roomJid, DiscoType.INFO); helper.start(disco); return helper; } @@ -72,7 +73,7 @@ public MessageResponseHelper requestRoomInfo(strin /// Returns a MessageResponseHelper listening for RequestRoomConfigurationMessage answers. public MessageResponseHelper requestRoomConfiguration(string roomJid, MUCAffiliation configLevel, MessageResponseHelper.OnMessageHandler onMessage, MessageResponseHelper.OnTimeoutHandler onTimeout) { - MessageResponseHelper helper = new MessageResponseHelper(CLIENT, onMessage, onTimeout); + MessageResponseHelper helper = new MessageResponseHelper(CONNECTION, onMessage, onTimeout); RequestRoomConfigurationMessage msg = new RequestRoomConfigurationMessage(roomJid, configLevel); helper.start(msg); return helper; @@ -89,8 +90,8 @@ public MessageResponseHelper requestRoomConfiguration(string roomJid, /// Returns a MessageResponseHelper listening for RoomInfoMessage answers. public MessageResponseHelper saveRoomConfiguration(string roomJid, DataForm roomConfiguration, MUCAffiliation configLevel, MessageResponseHelper.OnMessageHandler onMessage, MessageResponseHelper.OnTimeoutHandler onTimeout) { - MessageResponseHelper helper = new MessageResponseHelper(CLIENT, onMessage, onTimeout); - RoomInfoMessage msg = new RoomInfoMessage(CLIENT.getXMPPAccount().getFullJid(), roomJid, roomConfiguration, configLevel); + MessageResponseHelper helper = new MessageResponseHelper(CONNECTION, onMessage, onTimeout); + RoomInfoMessage msg = new RoomInfoMessage(CONNECTION.account.getFullJid(), roomJid, roomConfiguration, configLevel); helper.start(msg); return helper; } @@ -105,11 +106,11 @@ public MessageResponseHelper saveRoomConfiguration(string roomJid, Da /// Returns a MessageResponseHelper listening for MUCChangeNicknameMessage answers. public MessageResponseHelper changeNickname(string roomJid, string newNickname, MessageResponseHelper.OnMessageHandler onMessage, MessageResponseHelper.OnTimeoutHandler onTimeout) { - MessageResponseHelper helper = new MessageResponseHelper(CLIENT, onMessage, onTimeout) + MessageResponseHelper helper = new MessageResponseHelper(CONNECTION, onMessage, onTimeout) { matchId = false }; - MUCChangeNicknameMessage msg = new MUCChangeNicknameMessage(CLIENT.getXMPPAccount().getFullJid(), roomJid, newNickname); + MUCChangeNicknameMessage msg = new MUCChangeNicknameMessage(CONNECTION.account.getFullJid(), roomJid, newNickname); helper.start(msg); return helper; } @@ -125,8 +126,8 @@ public MessageResponseHelper changeNickname(string roomJid, str /// Returns a MessageResponseHelper listening for KickOccupantMessage answers. public MessageResponseHelper kickOccupant(string roomJid, string nickname, string reason, MessageResponseHelper.OnMessageHandler onMessage, MessageResponseHelper.OnTimeoutHandler onTimeout) { - MessageResponseHelper helper = new MessageResponseHelper(CLIENT, onMessage, onTimeout); - KickOccupantMessage msg = new KickOccupantMessage(CLIENT.getXMPPAccount().getFullJid(), roomJid, nickname, reason); + MessageResponseHelper helper = new MessageResponseHelper(CONNECTION, onMessage, onTimeout); + KickOccupantMessage msg = new KickOccupantMessage(CONNECTION.account.getFullJid(), roomJid, nickname, reason); helper.start(msg); return helper; } @@ -142,8 +143,8 @@ public MessageResponseHelper kickOccupant(string roomJid, string nick /// Returns a MessageResponseHelper listening for BanOccupantMessage answers. public MessageResponseHelper banOccupant(string roomJid, string jid, string reason, MessageResponseHelper.OnMessageHandler onMessage, MessageResponseHelper.OnTimeoutHandler onTimeout) { - MessageResponseHelper helper = new MessageResponseHelper(CLIENT, onMessage, onTimeout); - BanOccupantMessage msg = new BanOccupantMessage(CLIENT.getXMPPAccount().getFullJid(), roomJid, jid, reason); + MessageResponseHelper helper = new MessageResponseHelper(CONNECTION, onMessage, onTimeout); + BanOccupantMessage msg = new BanOccupantMessage(CONNECTION.account.getFullJid(), roomJid, jid, reason); helper.start(msg); return helper; } @@ -158,8 +159,8 @@ public MessageResponseHelper banOccupant(string roomJid, string jid, /// Returns a MessageResponseHelper listening for BanListMessage answers. public MessageResponseHelper requestBanList(string roomJid, MessageResponseHelper.OnMessageHandler onMessage, MessageResponseHelper.OnTimeoutHandler onTimeout) { - MessageResponseHelper helper = new MessageResponseHelper(CLIENT, onMessage, onTimeout); - BanListMessage msg = new BanListMessage(CLIENT.getXMPPAccount().getFullJid(), roomJid); + MessageResponseHelper helper = new MessageResponseHelper(CONNECTION, onMessage, onTimeout); + BanListMessage msg = new BanListMessage(CONNECTION.account.getFullJid(), roomJid); helper.start(msg); return helper; } @@ -174,8 +175,8 @@ public MessageResponseHelper requestBanList(string roomJid, MessageRe /// Returns a MessageResponseHelper listening for UpdateBanListMessage answers. public MessageResponseHelper updateBanList(string roomJid, List changedUsers, MessageResponseHelper.OnMessageHandler onMessage, MessageResponseHelper.OnTimeoutHandler onTimeout) { - MessageResponseHelper helper = new MessageResponseHelper(CLIENT, onMessage, onTimeout); - UpdateBanListMessage msg = new UpdateBanListMessage(CLIENT.getXMPPAccount().getFullJid(), roomJid, changedUsers); + MessageResponseHelper helper = new MessageResponseHelper(CONNECTION, onMessage, onTimeout); + UpdateBanListMessage msg = new UpdateBanListMessage(CONNECTION.account.getFullJid(), roomJid, changedUsers); helper.start(msg); return helper; } diff --git a/XMPP_API/Classes/Network/OmemoHelper.cs b/XMPP_API/Classes/Network/OmemoHelper.cs index 9808fe2b4..6c3536295 100644 --- a/XMPP_API/Classes/Network/OmemoHelper.cs +++ b/XMPP_API/Classes/Network/OmemoHelper.cs @@ -8,7 +8,7 @@ using XMPP_API.Classes.Crypto; using XMPP_API.Classes.Events; using XMPP_API.Classes.Network.XML.Messages; -using XMPP_API.Classes.Network.XML.Messages.XEP_0060; +using XMPP_API.Classes.Network.XML.Messages.Helper; using XMPP_API.Classes.Network.XML.Messages.XEP_0384; using XMPP_API.Classes.Network.XML.Messages.XEP_0384.Signal.Session; @@ -24,14 +24,6 @@ public class OmemoHelper : IDisposable private readonly XMPPConnection2 CONNECTION; private uint tmpDeviceId; - private MessageResponseHelper requestDeviceListHelper; - private MessageResponseHelper updateDeviceListHelper; - private MessageResponseHelper announceBundleInfoHelper; - - private MessageResponseHelper requestDeviceListStatelessHelper; - private MessageResponseHelper resetDeviceListStatelessHelper; - private Action requestDeviceListStatelessOnResult; - private Action resetDeviceListStatelessOnResult; // Keep sessions during App runtime: private readonly Dictionary OMEMO_SESSIONS; @@ -110,35 +102,6 @@ public void reset() CONNECTION.NewValidMessage += CONNECTION_ConnectionNewValidMessage; tmpDeviceId = 0; - - if (requestDeviceListHelper != null) - { - requestDeviceListHelper.Dispose(); - requestDeviceListHelper = null; - } - if (updateDeviceListHelper != null) - { - updateDeviceListHelper.Dispose(); - updateDeviceListHelper = null; - } - if (announceBundleInfoHelper != null) - { - announceBundleInfoHelper.Dispose(); - announceBundleInfoHelper = null; - } - if (requestDeviceListStatelessHelper != null) - { - requestDeviceListStatelessHelper.Dispose(); - requestDeviceListStatelessHelper = null; - } - if (resetDeviceListStatelessHelper != null) - { - resetDeviceListStatelessHelper.Dispose(); - resetDeviceListStatelessHelper = null; - } - - requestDeviceListStatelessOnResult = null; - resetDeviceListStatelessOnResult = null; } public SignalProtocolAddress newSession(string chatJid, OmemoBundleInformationResultMessage bundleInfoMsg) @@ -154,7 +117,7 @@ public SignalProtocolAddress newSession(string chatJid, uint recipientDeviceId, return address; } - public void sendOmemoMessage(OmemoMessageMessage msg, string chatJid, string accountJid) + public async Task sendOmemoMessageAsync(OmemoMessageMessage msg, string chatJid, string accountJid) { // Check if already trying to build a new session: if (MESSAGE_CACHE.ContainsKey(chatJid)) @@ -168,7 +131,7 @@ public void sendOmemoMessage(OmemoMessageMessage msg, string chatJid, string acc MESSAGE_CACHE[chatJid] = new Tuple, OmemoSessionBuildHelper>(new List(), sessionHelper); MESSAGE_CACHE[chatJid].Item1.Add(msg); Tuple subscription = OMEMO_STORE.LoadDeviceListSubscription(chatJid); - sessionHelper.start(subscription.Item1); + await sessionHelper.startAsync(subscription.Item1); } } @@ -179,132 +142,15 @@ public void onOmemoDeviceListEventMessage(OmemoDeviceListEventMessage msg) OMEMO_STORE.StoreDeviceListSubscription(senderBareJid, new Tuple(OmemoDeviceListSubscriptionState.SUBSCRIBED, DateTime.Now)); } - public void requestDeviceListStateless(Action onResult) - { - requestDeviceListStatelessOnResult = onResult; - - if (requestDeviceListStatelessHelper != null) - { - requestDeviceListStatelessHelper.Dispose(); - requestDeviceListStatelessHelper = null; - } - requestDeviceListStatelessHelper = new MessageResponseHelper(CONNECTION, onRequestDeviceListStatelessMessage, onRequestDeviceListStatelessTimeout); - OmemoRequestDeviceListMessage msg = new OmemoRequestDeviceListMessage(CONNECTION.account.getFullJid(), null); - requestDeviceListStatelessHelper.start(msg); - } - - public void resetDeviceListStateless(Action onResult) - { - resetDeviceListStatelessOnResult = onResult; - deleteDeviceListNode(); - } - - public void removePreKeyAndRepublish(uint preKeyId) + public async Task removePreKeyAndRepublishAsync(uint preKeyId) { CONNECTION.account.replaceOmemoPreKey(preKeyId, OMEMO_STORE); - announceBundleInfo(); + await announceBundleInfoAsync(); } #endregion #region --Misc Methods (Private)-- - private void deleteDeviceListNode() - { - if (resetDeviceListStatelessHelper != null) - { - resetDeviceListStatelessHelper.Dispose(); - resetDeviceListStatelessHelper = null; - } - - resetDeviceListStatelessHelper = new MessageResponseHelper(CONNECTION, onDeleteDeviceListNodeMessage, onDeleteDeviceListNodeTimeout); - PubSubDeleteNodeMessage msg = new PubSubDeleteNodeMessage(CONNECTION.account.getFullJid(), null, Consts.XML_XEP_0384_DEVICE_LIST_NODE); - resetDeviceListStatelessHelper.start(msg); - } - - private void setDeviceListToOwnDevice() - { - if (resetDeviceListStatelessHelper != null) - { - resetDeviceListStatelessHelper.Dispose(); - resetDeviceListStatelessHelper = null; - } - OmemoDevices devices = new OmemoDevices(); - devices.IDS.Add(CONNECTION.account.omemoDeviceId); - resetDeviceListStatelessHelper = new MessageResponseHelper(CONNECTION, onResetDeviceListStatelessMessage, onResetDeviceListStatelessTimeout); - OmemoSetDeviceListMessage msg = new OmemoSetDeviceListMessage(CONNECTION.account.getFullJid(), devices); - resetDeviceListStatelessHelper.start(msg); - } - - private bool onDeleteDeviceListNodeMessage(MessageResponseHelper helper, AbstractMessage msg) - { - if (msg is IQErrorMessage || (msg is IQMessage iMsg && string.Equals(iMsg.TYPE, IQMessage.RESULT))) - { - setDeviceListToOwnDevice(); - return true; - } - return false; - } - - private void onDeleteDeviceListNodeTimeout(MessageResponseHelper helper) - { - setDeviceListToOwnDevice(); - } - - private bool onResetDeviceListStatelessMessage(MessageResponseHelper helper, IQMessage msg) - { - if (msg is IQErrorMessage errMsg) - { - resetDeviceListStatelessOnResult?.Invoke(false); - resetDeviceListStatelessOnResult = null; - return true; - } - else if (msg is IQMessage) - { - DEVICES.IDS.Clear(); - DEVICES.IDS.Add(CONNECTION.account.omemoDeviceId); - resetDeviceListStatelessOnResult?.Invoke(true); - resetDeviceListStatelessOnResult = null; - return true; - } - return false; - } - - private void onResetDeviceListStatelessTimeout(MessageResponseHelper helper) - { - resetDeviceListStatelessOnResult?.Invoke(false); - resetDeviceListStatelessOnResult = null; - } - - private bool onRequestDeviceListStatelessMessage(MessageResponseHelper helper, IQMessage msg) - { - if (msg is OmemoDeviceListResultMessage devMsg) - { - requestDeviceListStatelessOnResult?.Invoke(true, devMsg.DEVICES); - requestDeviceListStatelessOnResult = null; - return true; - } - else if (msg is IQErrorMessage errMsg) - { - if (errMsg.ERROR_OBJ.ERROR_NAME == ErrorName.ITEM_NOT_FOUND) - { - requestDeviceListStatelessOnResult?.Invoke(true, new OmemoDevices()); - } - else - { - requestDeviceListStatelessOnResult?.Invoke(false, null); - } - requestDeviceListStatelessOnResult = null; - return true; - } - return false; - } - - private void onRequestDeviceListStatelessTimeout(MessageResponseHelper helper) - { - requestDeviceListStatelessOnResult?.Invoke(false, null); - requestDeviceListStatelessOnResult = null; - } - private void onSessionBuilderResult(OmemoSessionBuildHelper sender, OmemoSessionBuildResult result) { if (result.SUCCESS) @@ -329,80 +175,71 @@ private async Task sendAllOutstandingMessagesAsync(OmemoSession omemoSession) msg.encrypt(omemoSession, CONNECTION.account.omemoDeviceId); await CONNECTION.sendAsync(msg, true, false); } - cache.Item2.Dispose(); MESSAGE_CACHE.Remove(omemoSession.CHAT_JID); Logger.Info("[OMEMO HELPER] Send all outstanding OMEMO messages for: " + omemoSession.CHAT_JID + " to " + cache.Item1.Count + " recipient(s)."); } - private void requestDeviceList() + private async Task requestDeviceListAsync() { setState(OmemoHelperState.REQUESTING_DEVICE_LIST); + Logger.Info("[OMEMO HELPER](" + CONNECTION.account.getBareJid() + ") Requesting device list."); - if (requestDeviceListHelper != null) - { - requestDeviceListHelper.Dispose(); - } - requestDeviceListHelper = new MessageResponseHelper(CONNECTION, onRequestDeviceListMsg, onTimeout); - OmemoRequestDeviceListMessage msg = new OmemoRequestDeviceListMessage(CONNECTION.account.getFullJid(), null); - requestDeviceListHelper.start(msg); - } + MessageResponseHelperResult result = await CONNECTION.OMEMO_COMMAND_HELPER.requestDeviceListAsync(CONNECTION.account.getBareJid()); - private bool onRequestDeviceListMsg(MessageResponseHelper helper, AbstractMessage msg) - { - if (msg is OmemoDeviceListResultMessage devMsg) - { - updateDevicesIfNeeded(devMsg.DEVICES); - return true; - } - else if (msg is IQErrorMessage errMsg) + if (result.STATE == MessageResponseHelperResultState.SUCCESS) { - if (errMsg.ERROR_OBJ.ERROR_NAME == ErrorName.ITEM_NOT_FOUND) + if (result.RESULT is OmemoDeviceListResultMessage devMsg) { - Logger.Warn("[OMEMO HELPER](" + CONNECTION.account.getBareJid() + ") Failed to request OMEMO device list - node does not exist. Creating node."); - updateDevicesIfNeeded(null); + await updateDevicesIfNeededAsync(devMsg.DEVICES); } - else + else if (result.RESULT is IQErrorMessage errMsg) { - Logger.Error("[OMEMO HELPER](" + CONNECTION.account.getBareJid() + ") Failed to request OMEMO device list form: " + CONNECTION.account.user.domainPart + "\n" + errMsg.ERROR_OBJ.ToString()); - setState(OmemoHelperState.ERROR); + if (errMsg.ERROR_OBJ.ERROR_NAME == ErrorName.ITEM_NOT_FOUND) + { + Logger.Warn("[OMEMO HELPER](" + CONNECTION.account.getBareJid() + ") Failed to request OMEMO device list - node does not exist. Creating node."); + await updateDevicesIfNeededAsync(null); + } + else + { + Logger.Error("[OMEMO HELPER](" + CONNECTION.account.getBareJid() + ") Failed to request OMEMO device list form: " + CONNECTION.account.user.domainPart + "\n" + errMsg.ERROR_OBJ.ToString()); + setState(OmemoHelperState.ERROR); + } } - return true; } - return false; + else + { + onRequestError(result); + } } - private void announceBundleInfo() + private async Task announceBundleInfoAsync() { setState(OmemoHelperState.ANNOUNCING_BUNDLE_INFO); + Logger.Info("[OMEMO HELPER](" + CONNECTION.account.getBareJid() + ") Announcing bundle information for: " + CONNECTION.account.omemoDeviceId); - if (announceBundleInfoHelper != null) - { - announceBundleInfoHelper.Dispose(); - } - announceBundleInfoHelper = new MessageResponseHelper(CONNECTION, announceBundleInfoMsg, onTimeout); - OmemoSetBundleInformationMessage msg = new OmemoSetBundleInformationMessage(CONNECTION.account.getFullJid(), CONNECTION.account.getOmemoBundleInformation(), CONNECTION.account.omemoDeviceId); - announceBundleInfoHelper.start(msg); - } + MessageResponseHelperResult result = await CONNECTION.OMEMO_COMMAND_HELPER.setBundleInfoAsync(CONNECTION.account.getOmemoBundleInformation(), CONNECTION.account.omemoDeviceId); - private bool announceBundleInfoMsg(MessageResponseHelper helper, AbstractMessage msg) - { - if (msg is IQErrorMessage errMsg) + if (result.STATE == MessageResponseHelperResultState.SUCCESS) { - Logger.Error("[OMEMO HELPER](" + CONNECTION.account.getBareJid() + ") Failed to announce OMEMO bundle info to: " + CONNECTION.account.user.domainPart + "\n" + errMsg.ERROR_OBJ.ToString()); - setState(OmemoHelperState.ERROR); - return true; + if (result.RESULT is IQMessage) + { + Logger.Info("[OMEMO HELPER](" + CONNECTION.account.getBareJid() + ") Bundle info announced."); + setState(OmemoHelperState.ENABLED); + CONNECTION.account.omemoBundleInfoAnnounced = true; + } + else if (result.RESULT is IQErrorMessage errMsg) + { + Logger.Error("[OMEMO HELPER](" + CONNECTION.account.getBareJid() + ") Failed to announce OMEMO bundle info to: " + CONNECTION.account.user.domainPart + "\n" + errMsg.ERROR_OBJ.ToString()); + setState(OmemoHelperState.ERROR); + } } - else if (msg is IQMessage) + else { - Logger.Info("[OMEMO HELPER](" + CONNECTION.account.getBareJid() + ") Bundle info announced."); - setState(OmemoHelperState.ENABLED); - CONNECTION.account.omemoBundleInfoAnnounced = true; - return true; + onRequestError(result); } - return false; } - private void updateDevicesIfNeeded(OmemoDevices devicesRemote) + private async Task updateDevicesIfNeededAsync(OmemoDevices devicesRemote) { if (devicesRemote is null) { @@ -428,19 +265,11 @@ private void updateDevicesIfNeeded(OmemoDevices devicesRemote) if (updateDeviceList) { - setState(OmemoHelperState.UPDATING_DEVICE_LIST); - Logger.Info("[OMEMO HELPER](" + CONNECTION.account.getBareJid() + ") Updating device list."); - if (updateDeviceListHelper != null) - { - updateDeviceListHelper.Dispose(); - } - updateDeviceListHelper = new MessageResponseHelper(CONNECTION, updateDevicesIfNeededMsg, onTimeout); - OmemoSetDeviceListMessage msg = new OmemoSetDeviceListMessage(CONNECTION.account.getFullJid(), devicesRemote); - updateDeviceListHelper.start(msg); + await updateDeviceListAsync(devicesRemote); } else if (!CONNECTION.account.omemoBundleInfoAnnounced) { - announceBundleInfo(); + await announceBundleInfoAsync(); } else { @@ -449,35 +278,44 @@ private void updateDevicesIfNeeded(OmemoDevices devicesRemote) DEVICES = devicesRemote; } - private bool updateDevicesIfNeededMsg(MessageResponseHelper helper, AbstractMessage msg) + private async Task updateDeviceListAsync(OmemoDevices devices) { - if (msg is IQErrorMessage errMsg) - { - Logger.Error("[OMEMO HELPER](" + CONNECTION.account.getBareJid() + ") Failed to set OMEMO device list to: " + CONNECTION.account.user.domainPart + "\n" + errMsg.ERROR_OBJ.ToString()); - setState(OmemoHelperState.ERROR); - return true; - } - else if (msg is IQMessage) + setState(OmemoHelperState.UPDATING_DEVICE_LIST); + + Logger.Info("[OMEMO HELPER](" + CONNECTION.account.getBareJid() + ") Updating device list."); + MessageResponseHelperResult result = await CONNECTION.OMEMO_COMMAND_HELPER.setDeviceListAsync(devices); + + if (result.STATE == MessageResponseHelperResultState.SUCCESS) { - Logger.Info("[OMEMO HELPER](" + CONNECTION.account.getBareJid() + ") Device list updated."); - if (CONNECTION.account.omemoDeviceId == 0) - { - CONNECTION.account.omemoDeviceId = tmpDeviceId; - } - if (!CONNECTION.account.omemoBundleInfoAnnounced) + if (result.RESULT is IQMessage) { - announceBundleInfo(); + Logger.Info("[OMEMO HELPER](" + CONNECTION.account.getBareJid() + ") Device list updated."); + if (CONNECTION.account.omemoDeviceId == 0) + { + CONNECTION.account.omemoDeviceId = tmpDeviceId; + } + if (!CONNECTION.account.omemoBundleInfoAnnounced) + { + await announceBundleInfoAsync(); + } + else + { + setState(OmemoHelperState.ENABLED); + } } - else + else if (result.RESULT is IQErrorMessage errMsg) { - setState(OmemoHelperState.ENABLED); + Logger.Error("[OMEMO HELPER](" + CONNECTION.account.getBareJid() + ") Failed to set OMEMO device list to: " + CONNECTION.account.user.domainPart + "\n" + errMsg.ERROR_OBJ.ToString()); + setState(OmemoHelperState.ERROR); } - return true; } - return false; + else + { + onRequestError(result); + } } - private void onTimeout(MessageResponseHelper helper) + private void onRequestError(MessageResponseHelperResult result) { switch (STATE) { @@ -520,7 +358,7 @@ private async void CONNECTION_ConnectionNewValidMessage(IMessageSender sender, E } } - private void CONNECTION_ConnectionStateChanged(AbstractConnection2 connection, Events.ConnectionStateChangedEventArgs arg) + private async void CONNECTION_ConnectionStateChanged(AbstractConnection2 connection, Events.ConnectionStateChangedEventArgs arg) { switch (arg.newState) { @@ -532,7 +370,7 @@ private void CONNECTION_ConnectionStateChanged(AbstractConnection2 connection, E } else if (STATE == OmemoHelperState.DISABLED) { - requestDeviceList(); + await requestDeviceListAsync(); } break; diff --git a/XMPP_API/Classes/Network/StreamManagementHelper.cs b/XMPP_API/Classes/Network/StreamManagementHelper.cs index 50c6200d2..6d1dfac68 100644 --- a/XMPP_API/Classes/Network/StreamManagementHelper.cs +++ b/XMPP_API/Classes/Network/StreamManagementHelper.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.Threading.Tasks; using XMPP_API.Classes.Network.XML.Messages; using XMPP_API.Classes.Network.XML.Messages.XEP_0198; @@ -12,7 +8,7 @@ class StreamManagementHelper { //--------------------------------------------------------Attributes:-----------------------------------------------------------------\\ #region --Attributes-- - + #endregion //--------------------------------------------------------Constructor:----------------------------------------------------------------\\ @@ -35,15 +31,19 @@ public StreamManagementHelper() #endregion //--------------------------------------------------------Misc Methods:---------------------------------------------------------------\\ #region --Misc Methods (Public)-- +#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously public async Task onMessageReceivedAsync(AbstractMessage msg) +#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously { - if(msg is SMRequestMessage reqMsg) + if (msg is SMRequestMessage reqMsg) { } } +#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously public async Task onMessageSend(AbstractMessage msg) +#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously { } diff --git a/XMPP_API/Classes/Network/XML/Messages/Helper/AsyncMessageResponseHelper.cs b/XMPP_API/Classes/Network/XML/Messages/Helper/AsyncMessageResponseHelper.cs index 59ea81dd9..00ab6fe46 100644 --- a/XMPP_API/Classes/Network/XML/Messages/Helper/AsyncMessageResponseHelper.cs +++ b/XMPP_API/Classes/Network/XML/Messages/Helper/AsyncMessageResponseHelper.cs @@ -56,6 +56,9 @@ public void Dispose() public async Task> startAsync(AbstractMessage msg) { done = false; + sendId = msg.ID; + completionSource = new TaskCompletionSource>(); + MESSAGE_SENDER.NewValidMessage += MESSAGE_SENDER_NewValidMessage; bool success = await MESSAGE_SENDER.sendAsync(msg, CACHE_IF_NOT_CONNECTED); @@ -98,8 +101,6 @@ public void stop() #region --Misc Methods (Private)-- private async Task> waitForCompletionAsync() { - // Create all tasks: - completionSource = new TaskCompletionSource>(); timeoutTask = Task.Delay(TIMEOUT); // Wait for completion: @@ -140,6 +141,7 @@ private async void MESSAGE_SENDER_NewValidMessage(IMessageSender sender, Events. await METHOD_SEMA.WaitAsync(); if (disposed || done) { + METHOD_SEMA.Release(); return; } @@ -147,6 +149,7 @@ private async void MESSAGE_SENDER_NewValidMessage(IMessageSender sender, Events. { if (matchId && !string.Equals(sendId, msg.ID)) { + METHOD_SEMA.Release(); return; } diff --git a/XMPP_API/Classes/Network/XML/Messages/XEP-0384/OmemoMessageMessage.cs b/XMPP_API/Classes/Network/XML/Messages/XEP-0384/OmemoMessageMessage.cs index f8d466c80..8c109e708 100644 --- a/XMPP_API/Classes/Network/XML/Messages/XEP-0384/OmemoMessageMessage.cs +++ b/XMPP_API/Classes/Network/XML/Messages/XEP-0384/OmemoMessageMessage.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Text; +using System.Threading.Tasks; using System.Xml; using System.Xml.Linq; using XMPP_API.Classes.Crypto; @@ -146,10 +147,10 @@ public void encrypt(OmemoSession omemoSession, uint sourceDeviceId) /// The current OmemoHelper object of the current account. /// The local device id. /// True on success. - public bool decrypt(OmemoHelper helper, uint localeDeciceId) + public Task decryptAsync(OmemoHelper helper, uint localeDeciceId) { SignalProtocolAddress remoteAddress = new SignalProtocolAddress(Utils.getBareJidFromFullJid(FROM), SOURCE_DEVICE_ID); - return decrypt(helper.loadCipher(remoteAddress), remoteAddress, localeDeciceId, helper); + return decryptAsync(helper.loadCipher(remoteAddress), remoteAddress, localeDeciceId, helper); } /// @@ -161,7 +162,7 @@ public bool decrypt(OmemoHelper helper, uint localeDeciceId) /// The local device id. /// The current OmemoHelper object of the current account. If null, won't remove used PreKey. /// True on success. - public bool decrypt(SessionCipher cipher, SignalProtocolAddress remoteAddress, uint localeDeciceId, OmemoHelper helper) + public async Task decryptAsync(SessionCipher cipher, SignalProtocolAddress remoteAddress, uint localeDeciceId, OmemoHelper helper) { try { @@ -181,13 +182,13 @@ public bool decrypt(SessionCipher cipher, SignalProtocolAddress remoteAddress, u { PreKeySignalMessage preKeySignalMessage = new PreKeySignalMessage(encryptedKeyAuthTag); decryptedKeyAuthTag = cipher.decrypt(preKeySignalMessage); - if(!(helper is null)) + if (!(helper is null)) { May preKey = preKeySignalMessage.getPreKeyId(); - if(preKey.HasValue) + if (preKey.HasValue) { Logger.Info("Removing used PreKey."); - helper.removePreKeyAndRepublish(preKey.ForceGetValue()); + await helper.removePreKeyAndRepublishAsync(preKey.ForceGetValue()); } else { diff --git a/XMPP_API/Classes/Network/XML/Messages/XEP-0384/Signal/Session/OmemoSessionBuildHelper.cs b/XMPP_API/Classes/Network/XML/Messages/XEP-0384/Signal/Session/OmemoSessionBuildHelper.cs index c4a2fca5b..388859479 100644 --- a/XMPP_API/Classes/Network/XML/Messages/XEP-0384/Signal/Session/OmemoSessionBuildHelper.cs +++ b/XMPP_API/Classes/Network/XML/Messages/XEP-0384/Signal/Session/OmemoSessionBuildHelper.cs @@ -2,11 +2,13 @@ using Logging; using System; using System.Collections.Generic; +using System.Threading.Tasks; +using XMPP_API.Classes.Network.XML.Messages.Helper; using XMPP_API.Classes.Network.XML.Messages.XEP_0060; namespace XMPP_API.Classes.Network.XML.Messages.XEP_0384.Signal.Session { - public class OmemoSessionBuildHelper : IDisposable + public class OmemoSessionBuildHelper { //--------------------------------------------------------Attributes:-----------------------------------------------------------------\\ #region --Attributes-- @@ -22,9 +24,6 @@ public class OmemoSessionBuildHelper : IDisposable private IList toDoDevicesOwn; private SignalProtocolAddress curAddress; private readonly OmemoSession SESSION; - private MessageResponseHelper requestDeviceListHelper; - private MessageResponseHelper requestBundleInfoHelper; - private MessageResponseHelper subscribeToDeviceListHelper; #endregion //--------------------------------------------------------Constructor:----------------------------------------------------------------\\ @@ -44,8 +43,6 @@ internal OmemoSessionBuildHelper(string chatJid, string bareAccountJid, string f this.FULL_ACCOUNT_JID = fullAccountJid; this.OMEMO_HELPER = omemoHelper; this.STATE = OmemoSessionBuildHelperState.NOT_STARTED; - this.requestDeviceListHelper = null; - this.requestBundleInfoHelper = null; this.SESSION = new OmemoSession(chatJid); this.curAddress = null; } @@ -64,75 +61,155 @@ private void setState(OmemoSessionBuildHelperState newState) #endregion //--------------------------------------------------------Misc Methods:---------------------------------------------------------------\\ #region --Misc Methods (Public)-- - public void start(OmemoDeviceListSubscriptionState subscriptionState) + public async Task startAsync(OmemoDeviceListSubscriptionState subscriptionState) { switch (subscriptionState) { case OmemoDeviceListSubscriptionState.SUBSCRIBED: // Because we are subscribed, the device list should be up to date: IList devices = OMEMO_HELPER.OMEMO_STORE.LoadDevices(CHAT_JID); - createSessionsForDevices(devices); + await createSessionsForDevicesAsync(devices); break; default: - requestDeviceList(); + await requestDeviceListAsync(); break; } } - public void Dispose() - { - requestDeviceListHelper?.Dispose(); - requestBundleInfoHelper?.Dispose(); - subscribeToDeviceListHelper?.Dispose(); - } - #endregion #region --Misc Methods (Private)-- - private void requestDeviceList() + private async Task requestDeviceListAsync() { setState(OmemoSessionBuildHelperState.REQUESTING_DEVICE_LIST); - if (requestDeviceListHelper != null) + + MessageResponseHelperResult result = await CONNECTION.OMEMO_COMMAND_HELPER.requestDeviceListAsync(CHAT_JID); + + if (result.STATE == MessageResponseHelperResultState.SUCCESS) { - requestDeviceListHelper?.Dispose(); - requestDeviceListHelper = null; - } + if (result.RESULT is OmemoDeviceListResultMessage devMsg) + { + // Update devices in DB: + string chatJid = Utils.getBareJidFromFullJid(devMsg.getFrom()); + OMEMO_HELPER.OMEMO_STORE.StoreDevices(devMsg.DEVICES.toSignalProtocolAddressList(CHAT_JID)); - requestDeviceListHelper = new MessageResponseHelper(CONNECTION, onRequestDeviceListMessage, onTimeout); - OmemoRequestDeviceListMessage msg = new OmemoRequestDeviceListMessage(BARE_ACCOUNT_JID, CHAT_JID); - requestDeviceListHelper.start(msg); + if (devMsg.DEVICES.IDS.Count > 0) + { + await subscribeToDeviceListAsync(); + await createSessionsForDevicesAsync(devMsg.DEVICES.toSignalProtocolAddressList(CHAT_JID)); + } + else + { + Logger.Error("[OmemoSessionBuildHelper] Failed to establish session - " + CHAT_JID + " doesn't support OMEMO: No devices"); + setState(OmemoSessionBuildHelperState.ERROR); + ON_SESSION_RESULT(this, new OmemoSessionBuildResult(OmemoSessionBuildError.TARGET_DOES_NOT_SUPPORT_OMEMO)); + } + } + else if (result.RESULT is IQErrorMessage errMsg) + { + if (errMsg.ERROR_OBJ.ERROR_NAME == ErrorName.ITEM_NOT_FOUND) + { + Logger.Error("[OmemoSessionBuildHelper] Failed to establish session - " + CHAT_JID + " doesn't support OMEMO: " + errMsg.ERROR_OBJ.ToString()); + setState(OmemoSessionBuildHelperState.ERROR); + ON_SESSION_RESULT(this, new OmemoSessionBuildResult(OmemoSessionBuildError.TARGET_DOES_NOT_SUPPORT_OMEMO)); + } + else + { + Logger.Error("[OmemoSessionBuildHelper] Failed to establish session - request device list failed: " + errMsg.ERROR_OBJ.ToString()); + setState(OmemoSessionBuildHelperState.ERROR); + ON_SESSION_RESULT(this, new OmemoSessionBuildResult(OmemoSessionBuildError.REQUEST_DEVICE_LIST_IQ_ERROR)); + } + } + } + else + { + onRequestError(result); + } } - private void subscribeToDeviceList() + private async Task subscribeToDeviceListAsync() { setState(OmemoSessionBuildHelperState.SUBSCRIBING_TO_DEVICE_LIST); - if (subscribeToDeviceListHelper != null) + + MessageResponseHelperResult result = await CONNECTION.OMEMO_COMMAND_HELPER.subscribeToDeviceListAsync(CHAT_JID); + + if (result.STATE == MessageResponseHelperResultState.SUCCESS) { - subscribeToDeviceListHelper?.Dispose(); - subscribeToDeviceListHelper = null; + if (result.RESULT is PubSubSubscriptionMessage subMsg) + { + if (subMsg.SUBSCRIPTION != PubSubSubscriptionState.SUBSCRIBED) + { + Logger.Warn("[OmemoSessionBuildHelper] Failed to subscribe to device list node - " + CHAT_JID + " returned: " + subMsg.SUBSCRIPTION); + OMEMO_HELPER.OMEMO_STORE.StoreDeviceListSubscription(CHAT_JID, new Tuple(OmemoDeviceListSubscriptionState.NONE, DateTime.Now)); + } + else + { + OMEMO_HELPER.OMEMO_STORE.StoreDeviceListSubscription(CHAT_JID, new Tuple(OmemoDeviceListSubscriptionState.SUBSCRIBED, DateTime.Now)); + } + } + else if (result.RESULT is IQErrorMessage errMsg) + { + if (errMsg.ERROR_OBJ.ERROR_NAME == ErrorName.ITEM_NOT_FOUND) + { + Logger.Error("[OmemoSessionBuildHelper] Failed to subscribe to device list node - " + CHAT_JID + " returned node does not exist: " + errMsg.ERROR_OBJ.ToString()); + } + else + { + Logger.Warn("[OmemoSessionBuildHelper] Failed to subscribe to device list node: " + errMsg.ERROR_OBJ.ToString()); + } + OMEMO_HELPER.OMEMO_STORE.StoreDeviceListSubscription(CHAT_JID, new Tuple(OmemoDeviceListSubscriptionState.ERROR, DateTime.Now)); + } + } + else + { + onRequestError(result); } - - subscribeToDeviceListHelper = new MessageResponseHelper(CONNECTION, onSubscribeToDeviceListMessage, onTimeout); - OmemoSubscribeToDeviceListMessage msg = new OmemoSubscribeToDeviceListMessage(FULL_ACCOUNT_JID, BARE_ACCOUNT_JID, CHAT_JID); - subscribeToDeviceListHelper.start(msg); } - private void requestBundleInformation() + private async Task requestBundleInformationAsync() { setState(OmemoSessionBuildHelperState.REQUESTING_BUNDLE_INFORMATION); - if (requestBundleInfoHelper != null) + + MessageResponseHelperResult result = await CONNECTION.OMEMO_COMMAND_HELPER.requestBundleInformationAsync(curAddress.getName(), curAddress.getDeviceId()); + + if (result.STATE == MessageResponseHelperResultState.SUCCESS) { - requestBundleInfoHelper?.Dispose(); - requestBundleInfoHelper = null; + if (result.RESULT is OmemoBundleInformationResultMessage bundleMsg) + { + if (bundleMsg.BUNDLE_INFO.PUBLIC_PRE_KEYS.Count < 20) + { + Logger.Error("[OmemoSessionBuildHelper] Failed to establish session - " + curAddress.getName() + ':' + curAddress.getDeviceId() + " device offered less than 20 pre keys: " + bundleMsg.BUNDLE_INFO.PUBLIC_PRE_KEYS.Count); + } + else + { + Logger.Info("[OmemoSessionBuildHelper] Session with " + curAddress.getName() + ':' + curAddress.getDeviceId() + " established."); + SignalProtocolAddress address = OMEMO_HELPER.newSession(CHAT_JID, bundleMsg); + SessionCipher cipher = OMEMO_HELPER.loadCipher(address); + SESSION.DEVICE_SESSIONS.Add(curAddress.getDeviceId(), cipher); + } + await createSessionForNextDeviceAsync(); + } + else if (result.RESULT is IQErrorMessage errMsg) + { + if (errMsg.ERROR_OBJ.ERROR_NAME == ErrorName.ITEM_NOT_FOUND) + { + Logger.Error("[OmemoSessionBuildHelper] Failed to establish session - " + curAddress.getName() + ':' + curAddress.getDeviceId() + " doesn't support OMEMO: " + errMsg.ERROR_OBJ.ToString()); + } + else + { + Logger.Error("[OmemoSessionBuildHelper] Failed to establish session - request bundle info failed (" + curAddress.getName() + ':' + curAddress.getDeviceId() + "): " + errMsg.ERROR_OBJ.ToString()); + } + await createSessionForNextDeviceAsync(); + } + } + else + { + onRequestError(result); } - - requestBundleInfoHelper = new MessageResponseHelper(CONNECTION, onRequestBundleInformationMessage, onTimeout); - OmemoRequestBundleInformationMessage msg = new OmemoRequestBundleInformationMessage(FULL_ACCOUNT_JID, curAddress.getName(), curAddress.getDeviceId()); - requestBundleInfoHelper.start(msg); } - private void onTimeout(MessageResponseHelper helper) + private void onRequestError(MessageResponseHelperResult result) { switch (STATE) { @@ -156,7 +233,7 @@ private void onTimeout(MessageResponseHelper helper) } } - private void createSessionsForDevices(IList remoteDevices) + private async Task createSessionsForDevicesAsync(IList remoteDevices) { // Add remote devices: toDoDevicesRemote = remoteDevices; @@ -174,10 +251,10 @@ private void createSessionsForDevices(IList remoteDevices } } - createSessionForNextDevice(); + await createSessionForNextDeviceAsync(); } - private void createSessionForNextDevice() + private async Task createSessionForNextDeviceAsync() { if ((toDoDevicesRemote is null || toDoDevicesRemote.Count <= 0) && (toDoDevicesOwn is null || toDoDevicesOwn.Count <= 0)) { @@ -210,133 +287,13 @@ private void createSessionForNextDevice() { SessionCipher cipher = OMEMO_HELPER.loadCipher(curAddress); SESSION.DEVICE_SESSIONS.Add(curAddress.getDeviceId(), cipher); - createSessionForNextDevice(); - } - else - { - requestBundleInformation(); - } - } - } - - private bool onRequestDeviceListMessage(MessageResponseHelper helper, IQMessage msg) - { - if (STATE != OmemoSessionBuildHelperState.REQUESTING_DEVICE_LIST) - { - return true; - } - - if (msg is OmemoDeviceListResultMessage devMsg) - { - // Update devices in DB: - string chatJid = Utils.getBareJidFromFullJid(devMsg.getFrom()); - OMEMO_HELPER.OMEMO_STORE.StoreDevices(devMsg.DEVICES.toSignalProtocolAddressList(CHAT_JID)); - - if (devMsg.DEVICES.IDS.Count > 0) - { - subscribeToDeviceList(); - createSessionsForDevices(devMsg.DEVICES.toSignalProtocolAddressList(CHAT_JID)); - } - else - { - Logger.Error("[OmemoSessionBuildHelper] Failed to establish session - " + CHAT_JID + " doesn't support OMEMO: No devices"); - setState(OmemoSessionBuildHelperState.ERROR); - ON_SESSION_RESULT(this, new OmemoSessionBuildResult(OmemoSessionBuildError.TARGET_DOES_NOT_SUPPORT_OMEMO)); - } - return true; - } - else if (msg is IQErrorMessage errMsg) - { - if (errMsg.ERROR_OBJ.ERROR_NAME == ErrorName.ITEM_NOT_FOUND) - { - Logger.Error("[OmemoSessionBuildHelper] Failed to establish session - " + CHAT_JID + " doesn't support OMEMO: " + errMsg.ERROR_OBJ.ToString()); - setState(OmemoSessionBuildHelperState.ERROR); - ON_SESSION_RESULT(this, new OmemoSessionBuildResult(OmemoSessionBuildError.TARGET_DOES_NOT_SUPPORT_OMEMO)); - } - else - { - Logger.Error("[OmemoSessionBuildHelper] Failed to establish session - request device list failed: " + errMsg.ERROR_OBJ.ToString()); - setState(OmemoSessionBuildHelperState.ERROR); - ON_SESSION_RESULT(this, new OmemoSessionBuildResult(OmemoSessionBuildError.REQUEST_DEVICE_LIST_IQ_ERROR)); - } - return true; - } - return false; - } - - private bool onSubscribeToDeviceListMessage(MessageResponseHelper helper, IQMessage msg) - { - if (STATE != OmemoSessionBuildHelperState.SUBSCRIBING_TO_DEVICE_LIST) - { - return true; - } - - if (msg is PubSubSubscriptionMessage subMsg) - { - if (subMsg.SUBSCRIPTION != PubSubSubscriptionState.SUBSCRIBED) - { - Logger.Warn("[OmemoSessionBuildHelper] Failed to subscribe to device list node - " + CHAT_JID + " returned: " + subMsg.SUBSCRIPTION); - OMEMO_HELPER.OMEMO_STORE.StoreDeviceListSubscription(CHAT_JID, new Tuple(OmemoDeviceListSubscriptionState.NONE, DateTime.Now)); - } - else - { - OMEMO_HELPER.OMEMO_STORE.StoreDeviceListSubscription(CHAT_JID, new Tuple(OmemoDeviceListSubscriptionState.SUBSCRIBED, DateTime.Now)); - } - return true; - } - else if (msg is IQErrorMessage errMsg) - { - if (errMsg.ERROR_OBJ.ERROR_NAME == ErrorName.ITEM_NOT_FOUND) - { - Logger.Error("[OmemoSessionBuildHelper] Failed to subscribe to device list node - " + CHAT_JID + " returned node does not exist: " + errMsg.ERROR_OBJ.ToString()); - } - else - { - Logger.Warn("[OmemoSessionBuildHelper] Failed to subscribe to device list node: " + errMsg.ERROR_OBJ.ToString()); - } - OMEMO_HELPER.OMEMO_STORE.StoreDeviceListSubscription(CHAT_JID, new Tuple(OmemoDeviceListSubscriptionState.ERROR, DateTime.Now)); - return true; - } - return false; - } - - private bool onRequestBundleInformationMessage(MessageResponseHelper helper, IQMessage msg) - { - if (STATE != OmemoSessionBuildHelperState.REQUESTING_BUNDLE_INFORMATION) - { - return true; - } - - if (msg is OmemoBundleInformationResultMessage bundleMsg) - { - if (bundleMsg.BUNDLE_INFO.PUBLIC_PRE_KEYS.Count < 20) - { - Logger.Error("[OmemoSessionBuildHelper] Failed to establish session - " + curAddress.getName() + ':' + curAddress.getDeviceId() + " device offered less than 20 pre keys: " + bundleMsg.BUNDLE_INFO.PUBLIC_PRE_KEYS.Count); - } - else - { - Logger.Info("[OmemoSessionBuildHelper] Session with " + curAddress.getName() + ':' + curAddress.getDeviceId() + " established."); - SignalProtocolAddress address = OMEMO_HELPER.newSession(CHAT_JID, bundleMsg); - SessionCipher cipher = OMEMO_HELPER.loadCipher(address); - SESSION.DEVICE_SESSIONS.Add(curAddress.getDeviceId(), cipher); - } - createSessionForNextDevice(); - return true; - } - else if (msg is IQErrorMessage errMsg) - { - if (errMsg.ERROR_OBJ.ERROR_NAME == ErrorName.ITEM_NOT_FOUND) - { - Logger.Error("[OmemoSessionBuildHelper] Failed to establish session - " + curAddress.getName() + ':' + curAddress.getDeviceId() + " doesn't support OMEMO: " + errMsg.ERROR_OBJ.ToString()); + await createSessionForNextDeviceAsync(); } else { - Logger.Error("[OmemoSessionBuildHelper] Failed to establish session - request bundle info failed (" + curAddress.getName() + ':' + curAddress.getDeviceId() + "): " + errMsg.ERROR_OBJ.ToString()); + await requestBundleInformationAsync(); } - createSessionForNextDevice(); - return true; } - return false; } #endregion diff --git a/XMPP_API/Classes/Network/XMPPConnection2.cs b/XMPP_API/Classes/Network/XMPPConnection2.cs index 9da1b36ef..75008fe45 100644 --- a/XMPP_API/Classes/Network/XMPPConnection2.cs +++ b/XMPP_API/Classes/Network/XMPPConnection2.cs @@ -64,6 +64,11 @@ public class XMPPConnection2 : AbstractConnection2, IMessageSender private bool reconnectRequested; private TimeSpan timeout; + public readonly GeneralCommandHelper GENERAL_COMMAND_HELPER; + public readonly MUCCommandHelper MUC_COMMAND_HELPER; + public readonly PubSubCommandHelper PUB_SUB_COMMAND_HELPER; + public readonly OmemoCommandHelper OMEMO_COMMAND_HELPER; + #endregion //--------------------------------------------------------Constructor:----------------------------------------------------------------\\ #region --Constructors-- @@ -91,6 +96,11 @@ public XMPPConnection2(XMPPAccount account) : base(account) this.reconnectRequested = false; this.timeout = TimeSpan.FromMilliseconds(CONNECTION_TIMEOUT); + this.GENERAL_COMMAND_HELPER = new GeneralCommandHelper(this); + this.MUC_COMMAND_HELPER = new MUCCommandHelper(this); + this.PUB_SUB_COMMAND_HELPER = new PubSubCommandHelper(this); + this.OMEMO_COMMAND_HELPER = new OmemoCommandHelper(this); + // The order in which new messages should get processed (TLS -- SASL -- Stream Management -- Resource binding -- ...). // https://xmpp.org/extensions/xep-0170.html //------------------------------------------------------------- diff --git a/XMPP_API/Classes/OmemoCommandHelper.cs b/XMPP_API/Classes/OmemoCommandHelper.cs index 0bc041d29..1ae8676ff 100644 --- a/XMPP_API/Classes/OmemoCommandHelper.cs +++ b/XMPP_API/Classes/OmemoCommandHelper.cs @@ -1,4 +1,9 @@ -using XMPP_API.Classes.Network.XML.Messages; +using System; +using System.Threading.Tasks; +using XMPP_API.Classes.Network; +using XMPP_API.Classes.Network.XML.Messages; +using XMPP_API.Classes.Network.XML.Messages.Helper; +using XMPP_API.Classes.Network.XML.Messages.XEP_0060; using XMPP_API.Classes.Network.XML.Messages.XEP_0384; namespace XMPP_API.Classes @@ -7,7 +12,7 @@ public class OmemoCommandHelper { //--------------------------------------------------------Attributes:-----------------------------------------------------------------\\ #region --Attributes-- - private readonly XMPPClient CLIENT; + private readonly XMPPConnection2 CONNECTION; #endregion //--------------------------------------------------------Constructor:----------------------------------------------------------------\\ @@ -18,48 +23,92 @@ public class OmemoCommandHelper /// /// 17/03/2018 Created [Fabian Sauter] /// - public OmemoCommandHelper(XMPPClient client) + public OmemoCommandHelper(XMPPConnection2 connection) { - this.CLIENT = client; + this.CONNECTION = connection; } #endregion //--------------------------------------------------------Set-, Get- Methods:---------------------------------------------------------\\ #region --Set-, Get- Methods-- + /// + /// Sends an OmemoSetBundleInformationMessage for updating the given bundle information and device id. + /// + /// The bundle information you want to update. + /// The device id for the given bundle information. + /// The OmemoSetBundleInformationMessage result. + public async Task> setBundleInfoAsync(OmemoBundleInformation bundleInfo, uint deviceId) + { + Predicate predicate = (x) => { return true; }; + AsyncMessageResponseHelper helper = new AsyncMessageResponseHelper(CONNECTION, predicate); + OmemoSetBundleInformationMessage msg = new OmemoSetBundleInformationMessage(CONNECTION.account.getFullJid(), bundleInfo, deviceId); + return await helper.startAsync(msg); + } + /// + /// Sends an OmemoSetDeviceListMessage to update your OMEMO device list with the given devices. + /// + /// The new OMEMO device list. + /// The OmemoSetDeviceListMessage result. + public async Task> setDeviceListAsync(OmemoDevices devices) + { + Predicate predicate = (x) => { return true; }; + AsyncMessageResponseHelper helper = new AsyncMessageResponseHelper(CONNECTION, predicate); + OmemoSetDeviceListMessage msg = new OmemoSetDeviceListMessage(CONNECTION.account.getFullJid(), devices); + return await helper.startAsync(msg); + } #endregion //--------------------------------------------------------Misc Methods:---------------------------------------------------------------\\ #region --Misc Methods (Public)-- /// - /// Sends a OmemoRequestBundleInformationMessage to requests the OMEMO bundle information of the given target and deviceId. + /// Sends an OmemoRequestBundleInformationMessage to requests the OMEMO bundle information of the given target and deviceId. /// - /// The bare JID of the target you want to request the OMEMO bundle information from. e.g. 'conference.jabber.org' + /// The bare JID of the target you want to request the OMEMO bundle information from. e.g. 'conference.jabber.org' /// The device id you want to request the OMEMO bundle information for. - /// The method that should get executed once the helper receives a new valid message. - /// The method that should get executed once the helper timeout gets triggered. - /// Returns a MessageResponseHelper listening for OmemoRequestBundleInformationMessage answers. - public MessageResponseHelper requestBundleInformation(string to, uint deviceId, MessageResponseHelper.OnMessageHandler onMessage, MessageResponseHelper.OnTimeoutHandler onTimeout) + /// The OmemoRequestBundleInformationMessage result. + public async Task> requestBundleInformationAsync(string toBareJid, uint deviceId) + { + Predicate predicate = (x) => { return x is OmemoBundleInformationResultMessage || x is IQErrorMessage; }; + AsyncMessageResponseHelper helper = new AsyncMessageResponseHelper(CONNECTION, predicate); + OmemoRequestBundleInformationMessage msg = new OmemoRequestBundleInformationMessage(CONNECTION.account.getFullJid(), toBareJid, deviceId); + return await helper.startAsync(msg); + } + + /// + /// Sends an OmemoRequestDeviceListMessage to requests the OMEMO device list of the given target. + /// + /// The bare JID of the target you want to request the OMEMO bundle information from. e.g. 'conference.jabber.org' + /// The device id you want to request the OMEMO device list for. + /// The OmemoRequestDeviceListMessage result. + public async Task> requestDeviceListAsync(string toBareJid) + { + Predicate predicate = (x) => { return x is OmemoDeviceListResultMessage || x is IQErrorMessage; }; + AsyncMessageResponseHelper helper = new AsyncMessageResponseHelper(CONNECTION, predicate); + OmemoRequestDeviceListMessage msg = new OmemoRequestDeviceListMessage(CONNECTION.account.getFullJid(), toBareJid); + return await helper.startAsync(msg); + } + + /// + /// Sends an OmemoSubscribeToDeviceListMessage to subscribe to targets device list. + /// + /// The bare JID of the target you want to subscribe to. e.g. 'conference.jabber.org' + /// The OmemoSubscribeToDeviceListMessage result. + public async Task> subscribeToDeviceListAsync(string toBareJid) { - MessageResponseHelper helper = new MessageResponseHelper(CLIENT, onMessage, onTimeout); - OmemoRequestBundleInformationMessage msg = new OmemoRequestBundleInformationMessage(CLIENT.getXMPPAccount().getFullJid(), to, deviceId); - helper.start(msg); - return helper; + Predicate predicate = (x) => { return x is PubSubSubscriptionMessage || x is IQErrorMessage; }; + AsyncMessageResponseHelper helper = new AsyncMessageResponseHelper(CONNECTION, predicate); + OmemoSubscribeToDeviceListMessage msg = new OmemoSubscribeToDeviceListMessage(CONNECTION.account.getFullJid(), CONNECTION.account.getBareJid(), toBareJid); + return await helper.startAsync(msg); } /// - /// Sends a OmemoRequestDeviceListMessage to requests the OMEMO device list of the given target. + /// Sends a PubSubDeleteNodeMessage to delete the device list node. /// - /// The bare JID of the target you want to request the OMEMO device list from. e.g. 'conference.jabber.org' - /// The method that should get executed once the helper receives a new valid message. - /// The method that should get executed once the helper timeout gets triggered. - /// Returns a MessageResponseHelper listening for OmemoRequestDeviceListMessage answers. - public MessageResponseHelper requestDeviceList(string to, MessageResponseHelper.OnMessageHandler onMessage, MessageResponseHelper.OnTimeoutHandler onTimeout) + /// The PubSubDeleteNodeMessage result. + public async Task> deleteDeviceListNodeAsync() { - MessageResponseHelper helper = new MessageResponseHelper(CLIENT, onMessage, onTimeout); - OmemoRequestDeviceListMessage msg = new OmemoRequestDeviceListMessage(CLIENT.getXMPPAccount().getFullJid(), to); - helper.start(msg); - return helper; + return await CONNECTION.PUB_SUB_COMMAND_HELPER.deleteNodeAsync(null, Consts.XML_XEP_0384_DEVICE_LIST_NODE); } #endregion diff --git a/XMPP_API/Classes/PubSubCommandHelper.cs b/XMPP_API/Classes/PubSubCommandHelper.cs index 8a4484993..7939df014 100644 --- a/XMPP_API/Classes/PubSubCommandHelper.cs +++ b/XMPP_API/Classes/PubSubCommandHelper.cs @@ -1,6 +1,9 @@ using System; using System.Collections.Generic; +using System.Threading.Tasks; +using XMPP_API.Classes.Network; using XMPP_API.Classes.Network.XML.Messages; +using XMPP_API.Classes.Network.XML.Messages.Helper; using XMPP_API.Classes.Network.XML.Messages.XEP_0004; using XMPP_API.Classes.Network.XML.Messages.XEP_0060; using XMPP_API.Classes.Network.XML.Messages.XEP_0402; @@ -11,7 +14,7 @@ public class PubSubCommandHelper { //--------------------------------------------------------Attributes:-----------------------------------------------------------------\\ #region --Attributes-- - private readonly XMPPClient CLIENT; + private readonly XMPPConnection2 CONNECTION; #endregion //--------------------------------------------------------Constructor:----------------------------------------------------------------\\ @@ -22,9 +25,9 @@ public class PubSubCommandHelper /// /// 16/06/2018 Created [Fabian Sauter] /// - public PubSubCommandHelper(XMPPClient client) + public PubSubCommandHelper(XMPPConnection2 connection) { - this.CLIENT = client; + this.CONNECTION = connection; } #endregion @@ -47,8 +50,8 @@ public string getPubSubServer() /// Returns a MessageResponseHelper listening for RequestBookmarksMessage answers. public MessageResponseHelper requestBookmars_xep_0048(MessageResponseHelper.OnMessageHandler onMessage, MessageResponseHelper.OnTimeoutHandler onTimeout) { - MessageResponseHelper helper = new MessageResponseHelper(CLIENT, onMessage, onTimeout); - Network.XML.Messages.XEP_0048.RequestBookmarksMessage msg = new Network.XML.Messages.XEP_0048.RequestBookmarksMessage(CLIENT.getXMPPAccount().getFullJid()); + MessageResponseHelper helper = new MessageResponseHelper(CONNECTION, onMessage, onTimeout); + Network.XML.Messages.XEP_0048.RequestBookmarksMessage msg = new Network.XML.Messages.XEP_0048.RequestBookmarksMessage(CONNECTION.account.getFullJid()); helper.start(msg); return helper; } @@ -62,8 +65,8 @@ public MessageResponseHelper requestBookmars_xep_0048(MessageResponse /// Returns a MessageResponseHelper listening for SetBookmarksMessage answers. public MessageResponseHelper setBookmars_xep_0048(IList conferences, MessageResponseHelper.OnMessageHandler onMessage, MessageResponseHelper.OnTimeoutHandler onTimeout) { - MessageResponseHelper helper = new MessageResponseHelper(CLIENT, onMessage, onTimeout); - Network.XML.Messages.XEP_0048.SetBookmarksMessage msg = new Network.XML.Messages.XEP_0048.SetBookmarksMessage(CLIENT.getXMPPAccount().getFullJid(), conferences); + MessageResponseHelper helper = new MessageResponseHelper(CONNECTION, onMessage, onTimeout); + Network.XML.Messages.XEP_0048.SetBookmarksMessage msg = new Network.XML.Messages.XEP_0048.SetBookmarksMessage(CONNECTION.account.getFullJid(), conferences); helper.start(msg); return helper; } @@ -77,8 +80,8 @@ public MessageResponseHelper setBookmars_xep_0048(IListReturns a MessageResponseHelper listening for RequestBookmarksMessage answers. public MessageResponseHelper requestBookmars_xep_0402(MessageResponseHelper.OnMessageHandler onMessage, MessageResponseHelper.OnTimeoutHandler onTimeout) { - MessageResponseHelper helper = new MessageResponseHelper(CLIENT, onMessage, onTimeout); - RequestBookmarksMessage msg = new RequestBookmarksMessage(CLIENT.getXMPPAccount().getFullJid()); + MessageResponseHelper helper = new MessageResponseHelper(CONNECTION, onMessage, onTimeout); + RequestBookmarksMessage msg = new RequestBookmarksMessage(CONNECTION.account.getFullJid()); helper.start(msg); return helper; } @@ -93,8 +96,8 @@ public MessageResponseHelper requestBookmars_xep_0402(MessageResponse /// Returns a MessageResponseHelper listening for AddBookmarksMessage answers. public MessageResponseHelper addBookmark_xep_0402(ConferenceItem conferenceItem, MessageResponseHelper.OnMessageHandler onMessage, MessageResponseHelper.OnTimeoutHandler onTimeout) { - MessageResponseHelper helper = new MessageResponseHelper(CLIENT, onMessage, onTimeout); - AddBookmarkMessage msg = new AddBookmarkMessage(CLIENT.getXMPPAccount().getFullJid(), conferenceItem); + MessageResponseHelper helper = new MessageResponseHelper(CONNECTION, onMessage, onTimeout); + AddBookmarkMessage msg = new AddBookmarkMessage(CONNECTION.account.getFullJid(), conferenceItem); helper.start(msg); return helper; } @@ -109,8 +112,8 @@ public MessageResponseHelper addBookmark_xep_0402(ConferenceItem conf /// Returns a MessageResponseHelper listening for RemoveBookmarksMessage answers. public MessageResponseHelper removeBookmark_xep_0402(ConferenceItem conferenceItem, MessageResponseHelper.OnMessageHandler onMessage, MessageResponseHelper.OnTimeoutHandler onTimeout) { - MessageResponseHelper helper = new MessageResponseHelper(CLIENT, onMessage, onTimeout); - RemoveBookmarkMessage msg = new RemoveBookmarkMessage(CLIENT.getXMPPAccount().getFullJid(), conferenceItem); + MessageResponseHelper helper = new MessageResponseHelper(CONNECTION, onMessage, onTimeout); + RemoveBookmarkMessage msg = new RemoveBookmarkMessage(CONNECTION.account.getFullJid(), conferenceItem); helper.start(msg); return helper; } @@ -126,8 +129,8 @@ public MessageResponseHelper removeBookmark_xep_0402(ConferenceItem c /// Returns a MessageResponseHelper listening for DiscoverNodeMetadataMessage answers. public MessageResponseHelper requestNodeMetadata(string to, string nodeName, MessageResponseHelper.OnMessageHandler onMessage, MessageResponseHelper.OnTimeoutHandler onTimeout) { - MessageResponseHelper helper = new MessageResponseHelper(CLIENT, onMessage, onTimeout); - PubSubDiscoverNodeMetadataMessage msg = new PubSubDiscoverNodeMetadataMessage(CLIENT.getXMPPAccount().getFullJid(), to, nodeName); + MessageResponseHelper helper = new MessageResponseHelper(CONNECTION, onMessage, onTimeout); + PubSubDiscoverNodeMetadataMessage msg = new PubSubDiscoverNodeMetadataMessage(CONNECTION.account.getFullJid(), to, nodeName); helper.start(msg); return helper; } @@ -142,8 +145,8 @@ public MessageResponseHelper requestNodeMetadata(string to, string no /// Returns a MessageResponseHelper listening for PubSubSubscribeMessage answers. public MessageResponseHelper requestNodeSubscription(string to, string nodeName, MessageResponseHelper.OnMessageHandler onMessage, MessageResponseHelper.OnTimeoutHandler onTimeout) { - MessageResponseHelper helper = new MessageResponseHelper(CLIENT, onMessage, onTimeout); - PubSubSubscribeMessage msg = new PubSubSubscribeMessage(CLIENT.getXMPPAccount().getFullJid(), CLIENT.getXMPPAccount().getBareJid(), to, nodeName); + MessageResponseHelper helper = new MessageResponseHelper(CONNECTION, onMessage, onTimeout); + PubSubSubscribeMessage msg = new PubSubSubscribeMessage(CONNECTION.account.getFullJid(), CONNECTION.account.getBareJid(), to, nodeName); helper.start(msg); return helper; } @@ -159,8 +162,8 @@ public MessageResponseHelper requestNodeSubscription(string to, strin /// Returns a MessageResponseHelper listening for PubSubCreateNodeMessage answers. public MessageResponseHelper createNode(string to, string nodeName, MessageResponseHelper.OnMessageHandler onMessage, MessageResponseHelper.OnTimeoutHandler onTimeout) { - MessageResponseHelper helper = new MessageResponseHelper(CLIENT, onMessage, onTimeout); - PubSubCreateNodeMessage msg = new PubSubCreateNodeMessage(CLIENT.getXMPPAccount().getFullJid(), to, nodeName); + MessageResponseHelper helper = new MessageResponseHelper(CONNECTION, onMessage, onTimeout); + PubSubCreateNodeMessage msg = new PubSubCreateNodeMessage(CONNECTION.account.getFullJid(), to, nodeName); helper.start(msg); return helper; } @@ -177,8 +180,8 @@ public MessageResponseHelper createNode(string to, string nodeName, M /// Returns a MessageResponseHelper listening for PubSubCreateNodeMessage answers. public MessageResponseHelper createNode(string to, string nodeName, DataForm config, MessageResponseHelper.OnMessageHandler onMessage, MessageResponseHelper.OnTimeoutHandler onTimeout) { - MessageResponseHelper helper = new MessageResponseHelper(CLIENT, onMessage, onTimeout); - PubSubCreateNodeMessage msg = new PubSubCreateNodeMessage(CLIENT.getXMPPAccount().getFullJid(), to, nodeName, config); + MessageResponseHelper helper = new MessageResponseHelper(CONNECTION, onMessage, onTimeout); + PubSubCreateNodeMessage msg = new PubSubCreateNodeMessage(CONNECTION.account.getFullJid(), to, nodeName, config); helper.start(msg); return helper; } @@ -187,17 +190,15 @@ public MessageResponseHelper createNode(string to, string nodeName, D /// Sends a PubSubDeleteNodeMessage to delete a pubsub node. /// https://xmpp.org/extensions/xep-0060.html#owner-delete /// - /// The target pubsub server (can be null). + /// The target pubsub server (can be null). /// The name of the node, you want to delete. - /// The method that should get executed once the helper receives a new valid message (can be null). - /// The method that should get executed once the helper timeout gets triggered (can be null). - /// Returns a MessageResponseHelper listening for PubSubDeleteNodeMessage answers. - public MessageResponseHelper deleteNode(string to, string nodeName, MessageResponseHelper.OnMessageHandler onMessage, MessageResponseHelper.OnTimeoutHandler onTimeout) + /// The result of the PubSubDeleteNodeMessage. + public async Task> deleteNodeAsync(string toBareJid, string nodeName) { - MessageResponseHelper helper = new MessageResponseHelper(CLIENT, onMessage, onTimeout); - PubSubDeleteNodeMessage msg = new PubSubDeleteNodeMessage(CLIENT.getXMPPAccount().getFullJid(), to, nodeName); - helper.start(msg); - return helper; + Predicate predicate = (x) => { return true; }; + AsyncMessageResponseHelper helper = new AsyncMessageResponseHelper(CONNECTION, predicate); + PubSubDeleteNodeMessage msg = new PubSubDeleteNodeMessage(CONNECTION.account.getFullJid(), toBareJid, nodeName); + return await helper.startAsync(msg); } /// @@ -210,8 +211,8 @@ public MessageResponseHelper deleteNode(string to, string nodeName, M /// Returns a MessageResponseHelper listening for PubSubRequestSubscriptionsMessage answers. public MessageResponseHelper requestSubscriptions(string to, MessageResponseHelper.OnMessageHandler onMessage, MessageResponseHelper.OnTimeoutHandler onTimeout) { - MessageResponseHelper helper = new MessageResponseHelper(CLIENT, onMessage, onTimeout); - PubSubRequestSubscriptionsMessage msg = new PubSubRequestSubscriptionsMessage(CLIENT.getXMPPAccount().getFullJid(), to); + MessageResponseHelper helper = new MessageResponseHelper(CONNECTION, onMessage, onTimeout); + PubSubRequestSubscriptionsMessage msg = new PubSubRequestSubscriptionsMessage(CONNECTION.account.getFullJid(), to); helper.start(msg); return helper; } diff --git a/XMPP_API/Classes/XMPPClient.cs b/XMPP_API/Classes/XMPPClient.cs index f8cf9943a..cc327af4b 100644 --- a/XMPP_API/Classes/XMPPClient.cs +++ b/XMPP_API/Classes/XMPPClient.cs @@ -42,10 +42,10 @@ public class XMPPClient : IMessageSender public event NewDeliveryReceiptHandler NewDeliveryReceipt; public event OmemoSessionBuildErrorEventHandler OmemoSessionBuildError; - public readonly GeneralCommandHelper GENERAL_COMMAND_HELPER; - public readonly MUCCommandHelper MUC_COMMAND_HELPER; - public readonly PubSubCommandHelper PUB_SUB_COMMAND_HELPER; - public readonly OmemoCommandHelper OMEMO_COMMAND_HELPER; + public GeneralCommandHelper GENERAL_COMMAND_HELPER => connection.GENERAL_COMMAND_HELPER; + public MUCCommandHelper MUC_COMMAND_HELPER => connection.MUC_COMMAND_HELPER; + public PubSubCommandHelper PUB_SUB_COMMAND_HELPER => connection.PUB_SUB_COMMAND_HELPER; + public OmemoCommandHelper OMEMO_COMMAND_HELPER => connection.OMEMO_COMMAND_HELPER; #endregion //--------------------------------------------------------Constructor:----------------------------------------------------------------\\ @@ -58,10 +58,6 @@ public class XMPPClient : IMessageSender /// public XMPPClient(XMPPAccount account) { - this.GENERAL_COMMAND_HELPER = new GeneralCommandHelper(this); - this.MUC_COMMAND_HELPER = new MUCCommandHelper(this); - this.PUB_SUB_COMMAND_HELPER = new PubSubCommandHelper(this); - this.OMEMO_COMMAND_HELPER = new OmemoCommandHelper(this); init(account); } @@ -124,7 +120,9 @@ public void setAccount(XMPPAccount account) #endregion //--------------------------------------------------------Misc Methods:---------------------------------------------------------------\\ #region --Misc Methods (Public)-- +#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously public async Task transferSocketOwnershipAsync() +#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously { //await connection?.transferSocketOwnershipAsync(); } @@ -154,7 +152,7 @@ public async Task disconnectAsync() await connection.disconnectAsyncs(); } - public void sendOmemoMessage(OmemoMessageMessage msg, string chatJid, string accountJid) + public async Task sendOmemoMessageAsync(OmemoMessageMessage msg, string chatJid, string accountJid) { if (connection.omemoHelper is null) { @@ -168,7 +166,7 @@ public void sendOmemoMessage(OmemoMessageMessage msg, string chatJid, string acc } else { - connection.omemoHelper.sendOmemoMessage(msg, chatJid, accountJid); + await connection.omemoHelper.sendOmemoMessageAsync(msg, chatJid, accountJid); } }