diff --git a/Data_Manager2/Classes/ConnectionHandler.cs b/Data_Manager2/Classes/ConnectionHandler.cs
index b96c9e7e7..36498196f 100644
--- a/Data_Manager2/Classes/ConnectionHandler.cs
+++ b/Data_Manager2/Classes/ConnectionHandler.cs
@@ -276,9 +276,9 @@ private void onClientDisconneting(XMPPClient client)
/// The Client which entered the state.
private void onClientConnected(XMPPClient client)
{
- Task.Run(() =>
+ Task.Run(async () =>
{
- client.GENERAL_COMMAND_HELPER.requestRoster(null, null);
+ await client.GENERAL_COMMAND_HELPER.sendRequestRosterMessageAsync();
client.PUB_SUB_COMMAND_HELPER.requestBookmars_xep_0048(null, null);
MUCHandler.INSTANCE.onClientConnected(client);
ClientConnected?.Invoke(this, new ClientConnectedEventArgs(client));
diff --git a/XMPP_API/Classes/GeneralCommandHelper.cs b/XMPP_API/Classes/GeneralCommandHelper.cs
index c55588e3e..c4f27abad 100644
--- a/XMPP_API/Classes/GeneralCommandHelper.cs
+++ b/XMPP_API/Classes/GeneralCommandHelper.cs
@@ -1,6 +1,8 @@
using Logging;
+using System;
using System.Threading.Tasks;
using XMPP_API.Classes.Network.XML.Messages;
+using XMPP_API.Classes.Network.XML.Messages.Helper;
using XMPP_API.Classes.Network.XML.Messages.XEP_0030;
using XMPP_API.Classes.Network.XML.Messages.XEP_0085;
@@ -61,15 +63,23 @@ public async Task setPreseceAsync(string from, string to, Presence prese
///
/// Sends a RosterRequestMessage to the server and requests the current roster.
///
- /// 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 RosterRequestMessage answers.
- public MessageResponseHelper requestRoster(MessageResponseHelper.OnMessageHandler onMessage, MessageResponseHelper.OnTimeoutHandler onTimeout)
+ /// The result of the request.
+ public async Task> requestRosterAsync()
{
- MessageResponseHelper helper = new MessageResponseHelper(CLIENT, onMessage, onTimeout);
+ Predicate predicate = (x) => { return true; };
+ AsyncMessageResponseHelper helper = new AsyncMessageResponseHelper(CLIENT, predicate);
RosterRequestMessage msg = new RosterRequestMessage(CLIENT.getXMPPAccount().getFullJid(), CLIENT.getXMPPAccount().getBareJid());
- helper.start(msg);
- return helper;
+ return await helper.startAsync(msg);
+ }
+
+ ///
+ /// Sends a RosterRequestMessage to the server and requests the current roster.
+ ///
+ /// 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);
}
///
diff --git a/XMPP_API/Classes/Network/XML/Messages/Helper/AsyncMessageResponseHelper.cs b/XMPP_API/Classes/Network/XML/Messages/Helper/AsyncMessageResponseHelper.cs
new file mode 100644
index 000000000..59ea81dd9
--- /dev/null
+++ b/XMPP_API/Classes/Network/XML/Messages/Helper/AsyncMessageResponseHelper.cs
@@ -0,0 +1,164 @@
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace XMPP_API.Classes.Network.XML.Messages.Helper
+{
+ public class AsyncMessageResponseHelper : IDisposable where T : AbstractAddressableMessage
+ {
+ //--------------------------------------------------------Attributes:-----------------------------------------------------------------\\
+ #region --Attributes--
+ private readonly Predicate IS_VALID_ANSWER;
+
+ private readonly IMessageSender MESSAGE_SENDER;
+ private readonly bool CACHE_IF_NOT_CONNECTED;
+ private readonly SemaphoreSlim METHOD_SEMA = new SemaphoreSlim(1, 1);
+
+ ///
+ /// Default timeout for requests is 5 seconds.
+ ///
+ public readonly TimeSpan TIMEOUT = TimeSpan.FromSeconds(5.0);
+ private Task timeoutTask;
+ private TaskCompletionSource> completionSource;
+
+ public bool matchId = true;
+ public string sendId;
+ private bool done;
+
+ private bool disposed;
+
+ #endregion
+ //--------------------------------------------------------Constructor:----------------------------------------------------------------\\
+ #region --Constructors--
+ public AsyncMessageResponseHelper(IMessageSender messageSender, Predicate isValidAnswer) : this(messageSender, isValidAnswer, false) { }
+
+ public AsyncMessageResponseHelper(IMessageSender messageSender, Predicate isValidAnswer, bool cacheIfNotConnected)
+ {
+ this.MESSAGE_SENDER = messageSender;
+ this.IS_VALID_ANSWER = isValidAnswer;
+ this.CACHE_IF_NOT_CONNECTED = cacheIfNotConnected;
+ }
+
+ #endregion
+ //--------------------------------------------------------Set-, Get- Methods:---------------------------------------------------------\\
+ #region --Set-, Get- Methods--
+
+
+ #endregion
+ //--------------------------------------------------------Misc Methods:---------------------------------------------------------------\\
+ #region --Misc Methods (Public)--
+ public void Dispose()
+ {
+ stop();
+ disposed = true;
+ }
+
+ public async Task> startAsync(AbstractMessage msg)
+ {
+ done = false;
+ MESSAGE_SENDER.NewValidMessage += MESSAGE_SENDER_NewValidMessage;
+
+ bool success = await MESSAGE_SENDER.sendAsync(msg, CACHE_IF_NOT_CONNECTED);
+ if (!success)
+ {
+ if (CACHE_IF_NOT_CONNECTED)
+ {
+ return new MessageResponseHelperResult(MessageResponseHelperResultState.WILL_SEND_LATER);
+ }
+ return new MessageResponseHelperResult(MessageResponseHelperResultState.SEND_FAILED);
+ }
+
+ if (disposed)
+ {
+ return new MessageResponseHelperResult(MessageResponseHelperResultState.DISPOSED);
+ }
+
+ return await waitForCompletionAsync();
+ }
+
+ public void stop()
+ {
+ if (!disposed)
+ {
+ done = true;
+ if (!(completionSource is null) && !completionSource.Task.IsCanceled && !completionSource.Task.IsCompleted && !completionSource.Task.IsFaulted)
+ {
+ completionSource.SetResult(new MessageResponseHelperResult(MessageResponseHelperResultState.TIMEOUT));
+ }
+
+ if (!(MESSAGE_SENDER is null))
+ {
+ MESSAGE_SENDER.NewValidMessage -= MESSAGE_SENDER_NewValidMessage;
+ }
+ }
+ }
+
+ #endregion
+
+ #region --Misc Methods (Private)--
+ private async Task> waitForCompletionAsync()
+ {
+ // Create all tasks:
+ completionSource = new TaskCompletionSource>();
+ timeoutTask = Task.Delay(TIMEOUT);
+
+ // Wait for completion:
+ Task resultTask = await Task.WhenAny(new Task[] { completionSource.Task, timeoutTask });
+ MessageResponseHelperResult result = null;
+
+ // Evaluate and return result:
+ if (resultTask == completionSource.Task)
+ {
+ if (completionSource.Task.IsCompleted)
+ {
+ result = completionSource.Task.Result;
+ }
+ else
+ {
+ result = new MessageResponseHelperResult(MessageResponseHelperResultState.ERROR);
+ }
+ }
+ else
+ {
+ result = new MessageResponseHelperResult(MessageResponseHelperResultState.TIMEOUT);
+ }
+
+ stop();
+ return result;
+ }
+
+ #endregion
+
+ #region --Misc Methods (Protected)--
+
+
+ #endregion
+ //--------------------------------------------------------Events:---------------------------------------------------------------------\\
+ #region --Events--
+ private async void MESSAGE_SENDER_NewValidMessage(IMessageSender sender, Events.NewValidMessageEventArgs args)
+ {
+ await METHOD_SEMA.WaitAsync();
+ if (disposed || done)
+ {
+ return;
+ }
+
+ if (args.MESSAGE is T msg)
+ {
+ if (matchId && !string.Equals(sendId, msg.ID))
+ {
+ return;
+ }
+
+ if (IS_VALID_ANSWER(msg))
+ {
+ completionSource.TrySetResult(new MessageResponseHelperResult(MessageResponseHelperResultState.SUCCESS, msg));
+ done = true;
+ }
+ }
+ METHOD_SEMA.Release();
+ }
+
+ #endregion
+ }
+}
diff --git a/XMPP_API/Classes/Network/XML/Messages/Helper/MessageResponseHelperResult.cs b/XMPP_API/Classes/Network/XML/Messages/Helper/MessageResponseHelperResult.cs
new file mode 100644
index 000000000..3f7b3e715
--- /dev/null
+++ b/XMPP_API/Classes/Network/XML/Messages/Helper/MessageResponseHelperResult.cs
@@ -0,0 +1,48 @@
+namespace XMPP_API.Classes.Network.XML.Messages.Helper
+{
+ public class MessageResponseHelperResult where T : AbstractAddressableMessage
+ {
+ //--------------------------------------------------------Attributes:-----------------------------------------------------------------\\
+ #region --Attributes--
+ public readonly MessageResponseHelperResultState STATE;
+ public readonly T RESULT;
+
+ #endregion
+ //--------------------------------------------------------Constructor:----------------------------------------------------------------\\
+ #region --Constructors--
+ internal MessageResponseHelperResult(MessageResponseHelperResultState state) : this(state, null) { }
+
+ internal MessageResponseHelperResult(MessageResponseHelperResultState state, T result)
+ {
+ this.STATE = state;
+ this.RESULT = result;
+ }
+
+ #endregion
+ //--------------------------------------------------------Set-, Get- Methods:---------------------------------------------------------\\
+ #region --Set-, Get- Methods--
+
+
+ #endregion
+ //--------------------------------------------------------Misc Methods:---------------------------------------------------------------\\
+ #region --Misc Methods (Public)--
+
+
+ #endregion
+
+ #region --Misc Methods (Private)--
+
+
+ #endregion
+
+ #region --Misc Methods (Protected)--
+
+
+ #endregion
+ //--------------------------------------------------------Events:---------------------------------------------------------------------\\
+ #region --Events--
+
+
+ #endregion
+ }
+}
diff --git a/XMPP_API/Classes/Network/XML/Messages/Helper/MessageResponseHelperResultState.cs b/XMPP_API/Classes/Network/XML/Messages/Helper/MessageResponseHelperResultState.cs
new file mode 100644
index 000000000..5b8d2e23a
--- /dev/null
+++ b/XMPP_API/Classes/Network/XML/Messages/Helper/MessageResponseHelperResultState.cs
@@ -0,0 +1,30 @@
+namespace XMPP_API.Classes.Network.XML.Messages.Helper
+{
+ public enum MessageResponseHelperResultState
+ {
+ ///
+ /// The request was successful.
+ ///
+ SUCCESS,
+ ///
+ /// A timeout occurred.
+ ///
+ TIMEOUT,
+ ///
+ /// The helper has been disposed.
+ ///
+ DISPOSED,
+ ///
+ /// An error occurred during sending the message.
+ ///
+ SEND_FAILED,
+ ///
+ /// A general error occurred.
+ ///
+ ERROR,
+ ///
+ /// Sending the message failed, but the message has been cached and will be send later.
+ ///
+ WILL_SEND_LATER
+ }
+}
diff --git a/XMPP_API/XMPP_API.csproj b/XMPP_API/XMPP_API.csproj
index af422c795..79547b17d 100644
--- a/XMPP_API/XMPP_API.csproj
+++ b/XMPP_API/XMPP_API.csproj
@@ -176,6 +176,7 @@
+
@@ -198,12 +199,14 @@
+
+