2using System.Text.RegularExpressions;
3using System.Threading.Tasks;
17 private readonly
string host;
18 private readonly
int port;
19 private readonly
bool tls;
20 private readonly
string userName;
21 private readonly
string password;
22 private readonly
string passwordMechanism;
23 private readonly
bool trustServer =
false;
24 private readonly
bool allowInsecureMechanisms =
false;
39 string PasswordMechanism,
bool TrustServer,
bool AllowInsecureMechanisms)
45 this.userName = UserName;
46 this.password = Password;
47 this.passwordMechanism = PasswordMechanism;
48 this.trustServer = TrustServer;
49 this.allowInsecureMechanisms = AllowInsecureMechanisms;
65 public static async Task<XmppBroker>
Create(
XmppBrokerNode Node,
string Host,
int Port,
bool Tls,
string UserName,
string Password,
66 string PasswordMechanism,
bool TrustServer,
bool AllowInsecureMechanisms)
68 XmppBroker Result =
new XmppBroker(Node, Host, Port, Tls, UserName, Password, PasswordMechanism, TrustServer, AllowInsecureMechanisms);
77 private async Task Open()
79 if (
string.IsNullOrEmpty(this.passwordMechanism))
81 this.xmppClient =
new XmppClient(this.host, this.port, this.userName, this.password,
"en",
86 this.xmppClient =
new XmppClient(this.host, this.port, this.userName, this.password, this.passwordMechanism,
"en",
87 typeof(XmppBroker).Assembly);
90 this.xmppClient.TrustServer = this.trustServer;
91 this.xmppClient.AllowEncryption = this.tls;
92 this.xmppClient.AllowCramMD5 = this.allowInsecureMechanisms;
93 this.xmppClient.AllowDigestMD5 = this.allowInsecureMechanisms;
94 this.xmppClient.AllowPlain = this.allowInsecureMechanisms;
95 this.xmppClient.AllowScramSHA1 = this.allowInsecureMechanisms;
97 this.xmppClient.OnStateChanged += this.XmppClient_OnStateChanged;
98 this.xmppClient.OnPresence += this.XmppClient_OnPresence;
99 this.xmppClient.OnPresenceSubscribe += this.XmppClient_OnPresenceSubscribe;
100 this.xmppClient.OnPresenceSubscribed += this.XmppClient_OnPresenceSubscribed;
101 this.xmppClient.OnPresenceUnsubscribe += this.XmppClient_OnPresenceUnsubscribe;
102 this.xmppClient.OnPresenceUnsubscribed += this.XmppClient_OnPresenceUnsubscribed;
103 this.xmppClient.OnRosterItemAdded += this.XmppClient_OnRosterItemAdded;
104 this.xmppClient.OnRosterItemRemoved += this.XmppClient_OnRosterItemRemoved;
105 this.xmppClient.OnRosterItemUpdated += this.XmppClient_OnRosterItemUpdated;
109 if (Node is XmppExtensionNode Extension &&
110 !Extension.IsRegisteredExtension(
this.xmppClient))
112 await Extension.RegisterExtension(this.xmppClient);
116 await this.xmppClient.
Connect();
119 private async Task Close()
121 if (!(this.xmppClient is
null))
123 foreach (INode Node
in await this.node.ChildNodes)
125 if (Node is XmppExtensionNode Extension &&
126 Extension.IsRegisteredExtension(
this.xmppClient))
128 await Extension.UnregisterExtension(this.xmppClient);
132 this.xmppClient.OnStateChanged -= this.XmppClient_OnStateChanged;
133 this.xmppClient.OnPresence -= this.XmppClient_OnPresence;
134 this.xmppClient.OnPresenceSubscribe -= this.XmppClient_OnPresenceSubscribe;
135 this.xmppClient.OnPresenceSubscribed -= this.XmppClient_OnPresenceSubscribed;
136 this.xmppClient.OnPresenceUnsubscribe -= this.XmppClient_OnPresenceUnsubscribe;
137 this.xmppClient.OnPresenceUnsubscribed -= this.XmppClient_OnPresenceUnsubscribed;
138 this.xmppClient.OnRosterItemAdded -= this.XmppClient_OnRosterItemAdded;
139 this.xmppClient.OnRosterItemRemoved -= this.XmppClient_OnRosterItemRemoved;
140 this.xmppClient.OnRosterItemUpdated -= this.XmppClient_OnRosterItemUpdated;
143 this.xmppClient =
null;
152 Task.Run(() => this.Close());
155 private async Task XmppClient_OnStateChanged(
object Sender,
XmppState NewState)
162 await this.node.RemoveErrorAsync(
"Offline");
163 await this.node.RemoveErrorAsync(
"Error");
167 await this.node.LogErrorAsync(
"Error",
"Connection to broker failed.");
171 await this.node.LogErrorAsync(
"Offline",
"Connection is closed.");
181 private async Task XmppClient_OnPresenceSubscribe(
object Sender,
PresenceEventArgs e)
183 if (this.node is
null)
191 if (
string.IsNullOrEmpty(this.node.AutoAcceptPattern))
196 await
RosterItem.LogInformationAsync(
"Presence subscription received and declined.");
203 Regex Parsed =
new Regex(this.node.AutoAcceptPattern, RegexOptions.Singleline | RegexOptions.IgnoreCase);
206 if (M.Success && M.Index == 0 && M.Length == e.
FromBareJID.Length)
213 await
RosterItem.LogInformationAsync(
"Presence subscription received and accepted.");
220 await
RosterItem.LogInformationAsync(
"Presence subscription received and declined.");
228 await
RosterItem.LogInformationAsync(
"Presence subscription received and declined.");
230 await this.node.LogErrorAsync(
"Unable to parse regular expression: " + ex.Message);
234 private async Task XmppClient_OnPresenceSubscribed(
object Sender,
PresenceEventArgs e)
236 if (this.node is
null)
240 await
RosterItem.LogInformationAsync(
"Subscribed.");
243 private async Task XmppClient_OnPresenceUnsubscribe(
object Sender,
PresenceEventArgs e)
247 if (this.node is
null)
259 private async Task XmppClient_OnPresenceUnsubscribed(
object Sender,
PresenceEventArgs e)
261 if (this.node is
null)
275 return Task.CompletedTask;
278 private async Task XmppClient_OnRosterItemAdded(
object Sender,
RosterItem Item)
280 if (this.node is
null)
283 RosterItemNode Node = await this.node.GetRosterItem(Item.
BareJid,
true);
285 Node.SubscriptionState != Item.State ||
286 Node.ContactName != Item.Name ||
287 Node.PendingSubscription != Item.PendingSubscription ||
288 !AreSame(Node.Groups, Item.
Groups);
292 Node.SubscriptionState = Item.
State;
293 Node.ContactName = Item.
Name;
295 Node.Groups = Item.Groups ??
new string[0];
297 await Node.UpdateAsync();
301 private static bool AreSame(
string[] A1,
string[] A2)
303 if ((A1 is
null) ^ (A2 is
null))
315 for (i = 0; i < c; i++)
324 private Task XmppClient_OnRosterItemUpdated(
object Sender,
RosterItem Item)
326 return this.XmppClient_OnRosterItemAdded(Sender, Item);
329 private async Task XmppClient_OnRosterItemRemoved(
object Sender,
RosterItem Item)
331 if (this.node is
null)
334 RosterItemNode Node = await this.node.GetRosterItem(Item.
BareJid,
false);
338 await Node.DestroyAsync();
Static class managing the application event log. Applications and services log events on this static ...
static void Exception(Exception Exception, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, params KeyValuePair< string, object >[] Tags)
Logs an exception. Event type will be determined by the severity of the exception.
Event arguments for presence events.
string FromBareJID
Bare JID of resource sending the presence.
async Task Decline()
Declines a subscription or unsubscription request.
async Task Accept()
Accepts a subscription or unsubscription request.
Maintains information about an item in the roster.
SubscriptionState State
roup Current subscription state.
string[] Groups
Any groups the roster item belongs to.
string BareJid
Bare JID of the roster item.
PendingSubscription PendingSubscription
If there's a pending unanswered presence subscription or unsubscription request made to the contact.
string Name
Name of the roster item.
Manages an XMPP client connection. Implements XMPP, as defined in https://tools.ietf....
Task OfflineAndDisposeAsync()
Sends an offline presence, and then disposes the object by calling DisposeAsync.
Task Connect()
Connects the client.
Represents an XMPP broker.
static async Task< XmppBroker > Create(XmppBrokerNode Node, string Host, int Port, bool Tls, string UserName, string Password, string PasswordMechanism, bool TrustServer, bool AllowInsecureMechanisms)
Creates an XMPP broker
void Dispose()
IDisposable.Dispose
Node representing an XMPP broker.
Interface for nodes that are published through the concentrator interface.
Task< IEnumerable< INode > > ChildNodes
Child nodes. If no child nodes are available, null is returned.
XmppState
State of XMPP connection.