Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
XmppBrokerNode.cs
1using System;
2using System.Collections;
3using System.Collections.Generic;
4using System.Threading.Tasks;
13using Waher.Things.Ip;
16
17namespace Waher.Things.Xmpp
18{
23 {
24 private readonly Dictionary<CaseInsensitiveString, RosterItemNode> roster = new Dictionary<CaseInsensitiveString, RosterItemNode>();
25 private string userName = string.Empty;
26 private string password = string.Empty;
27 private string passwordMechanism = string.Empty;
28 private string brokerKey = null;
29 private bool trustServer = false;
30 private bool allowInsecureMechanisms = false;
31
36 : base()
37 {
38 this.Port = 5222;
39 this.Tls = true;
40 }
41
45 [Page(2, "XMPP")]
46 [Header(13, "User Name:")]
47 [ToolTip(14, "User name used during authentication process.")]
48 [DefaultValueStringEmpty]
49 public string UserName
50 {
51 get => this.userName;
52 set => this.userName = value;
53 }
54
58 [Page(2, "XMPP")]
59 [Header(15, "Password:")]
60 [ToolTip(16, "Password used during authentication process.")]
61 [Masked]
62 [DefaultValueStringEmpty]
63 public string Password
64 {
65 get => this.password;
66 set => this.password = value;
67 }
68
72 [Page(2, "XMPP")]
73 [Header(17, "Password Hash Mechanism:")]
74 [ToolTip(18, "Mechanism used for password hash.")]
75 [DefaultValueStringEmpty]
76 public string PasswordMechanism
77 {
78 get => this.passwordMechanism;
79 set => this.passwordMechanism = value;
80 }
81
85 [Page(2, "XMPP")]
86 [Header(19, "Trust Server Certificate")]
87 [ToolTip(20, "If the server certificate should be trusted, even if it does not validate.")]
88 [DefaultValue(false)]
89 public bool TrustServer
90 {
91 get => this.trustServer;
92 set => this.trustServer = value;
93 }
94
98 [Page(2, "XMPP")]
99 [Header(21, "Allow Insecure Mechanisms")]
100 [ToolTip(22, "If insecure mechanisms are permitted during authentication.")]
101 [DefaultValue(false)]
103 {
104 get => this.allowInsecureMechanisms;
105 set => this.allowInsecureMechanisms = value;
106 }
107
111 [Page(28, "Roster", 110)]
112 [Header(32, "Auto-accept Pattern:")]
113 [ToolTip(33, "If a presence subscription comes from a JID that matches this regular expression, it will be automatically accepted.")]
114 public string AutoAcceptPattern { get; set; }
115
121 public override Task<string> GetTypeNameAsync(Language Language)
122 {
123 return Language.GetStringAsync(typeof(XmppBrokerNode), 23, "XMPP Broker");
124 }
125
131 public override Task<bool> AcceptsChildAsync(INode Child)
132 {
133 return Task.FromResult(Child is ConcentratorNode || Child is ConcentratorSourceNode || Child is ConcentratorPartitionNode ||
134 Child is ConcentratorDevice || Child is RosterItemNode || Child is XmppExtensionNode);
135 }
136
140 public override Task DestroyAsync()
141 {
142 if (!string.IsNullOrEmpty(this.brokerKey))
143 XmppBrokers.DestroyBroker(this.brokerKey);
144
145 return base.DestroyAsync();
146 }
147
151 [IgnoreMember]
152 public string Key
153 {
154 get
155 {
156 string PrevKey = this.brokerKey;
157 this.brokerKey = XmppBrokers.GetKey(this.Host, this.Port, this.Tls, this.userName, this.password, this.passwordMechanism);
158
159 if (PrevKey != this.brokerKey && !string.IsNullOrEmpty(PrevKey))
160 XmppBrokers.DestroyBroker(PrevKey);
161
162 return this.brokerKey;
163 }
164 }
165
169 protected override Task NodeUpdated()
170 {
171 this.GetBroker();
172
173 return base.NodeUpdated();
174 }
175
176 internal Task<XmppBroker> GetBroker()
177 {
178 return XmppBrokers.GetBroker(this, this.Key, this.Host, this.Port, this.Tls, this.userName, this.password,
179 this.passwordMechanism, this.trustServer, this.allowInsecureMechanisms);
180 }
181
182 #region ICommunicationLayer
183
188 public bool DecoupledEvents => true;
189
193 public void Add(ISniffer Sniffer)
194 {
195 this.GetBroker().Result?.Client?.Add(Sniffer);
196 }
197
201 public void AddRange(IEnumerable<ISniffer> Sniffers)
202 {
203 this.GetBroker().Result?.Client?.AddRange(Sniffers);
204 }
205
209 public bool Remove(ISniffer Sniffer)
210 {
211 return this.GetBroker().Result?.Client?.Remove(Sniffer) ?? false;
212 }
213
218 {
219 get { return this.GetBroker().Result?.Client?.Sniffers ?? new ISniffer[0]; }
220 }
221
225 public bool HasSniffers
226 {
227 get { return this.GetBroker().Result?.Client?.HasSniffers ?? false; }
228 }
229
233 public IEnumerator<ISniffer> GetEnumerator()
234 {
235 return new SnifferEnumerator(this.Sniffers);
236 }
237
238 IEnumerator IEnumerable.GetEnumerator()
239 {
240 return this.GetBroker().Result?.Client?.GetEnumerator() ?? new ISniffer[0].GetEnumerator();
241 }
242
247 public async Task ReceiveBinary(byte[] Data) => await ((await this.GetBroker()).Client?.ReceiveBinary(Data) ?? Task.CompletedTask);
248
253 public async Task TransmitBinary(byte[] Data) => await ((await this.GetBroker()).Client?.TransmitBinary(Data) ?? Task.CompletedTask);
254
259 public async Task ReceiveText(string Text) => await ((await this.GetBroker()).Client?.ReceiveText(Text) ?? Task.CompletedTask);
260
265 public async Task TransmitText(string Text) => await ((await this.GetBroker()).Client?.TransmitText(Text) ?? Task.CompletedTask);
266
271 public async Task Information(string Comment) => await ((await this.GetBroker()).Client?.Information(Comment) ?? Task.CompletedTask);
272
277 public async Task Warning(string Warning) => await ((await this.GetBroker()).Client?.Warning(Warning) ?? Task.CompletedTask);
278
283 public async Task Error(string Error) => await ((await this.GetBroker()).Client?.Error(Error) ?? Task.CompletedTask);
284
289 public async Task Exception(Exception Exception) => await ((await this.GetBroker()).Client?.Exception(Exception) ?? Task.CompletedTask);
290
295 public async Task Exception(string Exception) => await ((await this.GetBroker()).Client?.Exception(Exception) ?? Task.CompletedTask);
296
302 public async Task ReceiveBinary(DateTime Timestamp, byte[] Data) => await ((await this.GetBroker()).Client?.ReceiveBinary(Timestamp, Data) ?? Task.CompletedTask);
303
309 public async Task TransmitBinary(DateTime Timestamp, byte[] Data) => await ((await this.GetBroker()).Client?.TransmitBinary(Timestamp, Data) ?? Task.CompletedTask);
310
316 public async Task ReceiveText(DateTime Timestamp, string Text) => await ((await this.GetBroker()).Client?.ReceiveText(Timestamp, Text) ?? Task.CompletedTask);
317
323 public async Task TransmitText(DateTime Timestamp, string Text) => await ((await this.GetBroker()).Client?.TransmitText(Timestamp, Text) ?? Task.CompletedTask);
324
330 public async Task Information(DateTime Timestamp, string Comment) => await ((await this.GetBroker()).Client?.Information(Timestamp, Comment) ?? Task.CompletedTask);
331
337 public async Task Warning(DateTime Timestamp, string Warning) => await ((await this.GetBroker()).Client?.Warning(Timestamp, Warning) ?? Task.CompletedTask);
338
344 public async Task Error(DateTime Timestamp, string Error) => await ((await this.GetBroker()).Client?.Error(Timestamp, Error) ?? Task.CompletedTask);
345
351 public async Task Exception(DateTime Timestamp, string Exception) => await ((await this.GetBroker()).Client?.Exception(Timestamp, Exception) ?? Task.CompletedTask);
352
358 public async Task Exception(DateTime Timestamp, Exception Exception) => await ((await this.GetBroker()).Client?.Exception(Timestamp, Exception) ?? Task.CompletedTask);
359
360 #endregion
361
365 public override Task<IEnumerable<ICommand>> Commands => this.GetCommands();
366
371 public async Task<IEnumerable<ICommand>> GetCommands()
372 {
373 List<ICommand> Result = new List<ICommand>();
374
375 Result.AddRange(await base.Commands);
376 Result.Add(new ReconnectCommand((await this.GetBroker()).Client));
377
378 return Result;
379 }
380
387 public async override Task<IEnumerable<Parameter>> GetDisplayableParametersAsync(Language Language, RequestOrigin Caller)
388 {
389 LinkedList<Parameter> Result = await base.GetDisplayableParametersAsync(Language, Caller) as LinkedList<Parameter>;
390 XmppBroker Broker = await this.GetBroker();
391
392 Result.AddLast(new StringParameter("State", await Language.GetStringAsync(typeof(XmppBrokerNode), 27, "State"),
393 Broker.Client.State.ToString() ?? string.Empty));
394
395 return Result;
396 }
397
398 #region Roster
399
406 public async Task<RosterItemNode> GetRosterItem(string BareJID, bool CreateIfNotExists)
407 {
408 RosterItemNode Result;
409 bool Load;
410
411 lock (this.roster)
412 {
413 if (this.roster.TryGetValue(BareJID, out Result))
414 return Result;
415
416 Load = this.roster.Count == 0;
417 }
418
419 if (Load)
420 {
421 IEnumerable<INode> Children = await this.ChildNodes;
422
423 lock (this.roster)
424 {
425 foreach (INode Node in Children)
426 {
427 if (Node is RosterItemNode RosterItem)
428 this.roster[RosterItem.BareJID] = RosterItem;
429 }
430
431 if (this.roster.TryGetValue(BareJID, out Result))
432 return Result;
433 }
434 }
435
436 if (CreateIfNotExists)
437 {
438 Result = new RosterItemNode()
439 {
440 NodeId = await GetUniqueNodeId(this.NodeId + ", " + BareJID),
441 BareJID = BareJID
442 };
443
444 await this.AddAsync(Result);
445
446 return Result;
447 }
448 else
449 return null;
450 }
451
456 public override async Task AddAsync(INode Child)
457 {
458 await base.AddAsync(Child);
459
460 if (Child is RosterItemNode Item)
461 {
462 lock (this.roster)
463 {
464 this.roster[Item.BareJID] = Item;
465 }
466 }
467
468 if (Child is XmppExtensionNode Extension)
469 {
470 try
471 {
472 XmppBroker Broker = await this.GetBroker();
473 XmppClient Client = Broker.Client;
474
475 if (!Extension.IsRegisteredExtension(Client))
476 await Extension.RegisterExtension(Client);
477 }
478 catch (Exception ex)
479 {
480 await this.LogErrorAsync(ex.Message);
481 }
482 }
483 }
484
490 public override async Task<bool> RemoveAsync(INode Child)
491 {
492 if (!await base.RemoveAsync(Child))
493 return false;
494
495 if (Child is RosterItemNode Item)
496 {
497 lock (this.roster)
498 {
499 this.roster.Remove(Item.BareJID);
500 }
501 }
502
503 if (Child is XmppExtensionNode Extension)
504 {
505 try
506 {
507 XmppBroker Broker = await this.GetBroker();
508 XmppClient Client = Broker.Client;
509
510 if (Extension.IsRegisteredExtension(Client))
511 await Extension.UnregisterExtension(Client);
512 }
513 catch (Exception ex)
514 {
515 await this.LogErrorAsync(ex.Message);
516 }
517 }
518
519 return true;
520 }
521
522 #endregion
523
524 }
525}
Maintains information about an item in the roster.
Definition: RosterItem.cs:75
Manages an XMPP client connection. Implements XMPP, as defined in https://tools.ietf....
Definition: XmppClient.cs:59
XmppState State
Current state of connection.
Definition: XmppClient.cs:985
bool UnregisterExtension(IXmppExtension Extension)
Unregisters an extension on the client.
Definition: XmppClient.cs:7290
void RegisterExtension(IXmppExtension Extension)
Registers an extension with the client.
Definition: XmppClient.cs:7276
Contains information about a language.
Definition: Language.cs:17
Task< string > GetStringAsync(Type Type, int Id, string Default)
Gets the string value of a string ID. If no such string exists, a string is created with the default ...
Definition: Language.cs:209
string Host
Host name or IP address.
Definition: IpHost.cs:63
Node representing a port on an IP Host machine.
Definition: IpHostPort.cs:21
bool Tls
If connection is encrypted using TLS or not.
Definition: IpHostPort.cs:67
int Port
Port number.
Definition: IpHostPort.cs:55
virtual Task LogErrorAsync(string Body)
Logs an error message on the node.
static async Task< string > GetUniqueNodeId(string NodeId)
Gets a Node ID, based on NodeId that is not already available in the database.
Tokens available in request.
Definition: RequestOrigin.cs:9
Node representing an XMPP concentrator.
Base class for nodes in a remote concentrator.
Node representing a partition in a data source in an XMPP concentrator.
Node representing a data source in an XMPP concentrator.
Represents an XMPP broker.
Definition: XmppBroker.cs:14
Static class managing connections to XMPP brokers.
Definition: XmppBrokers.cs:12
static string GetKey(string Host, int Port, bool Tls, string UserName, string Password, string PasswordMechanism)
Gets sort key for XMPP broker
Definition: XmppBrokers.cs:25
static async Task< XmppBroker > GetBroker(XmppBrokerNode Node, string Key, string Host, int Port, bool Tls, string UserName, string Password, string PasswordMechanism, bool TrustServer, bool AllowInsecureMechanisms)
Gets an XMPP broker object instance.
Definition: XmppBrokers.cs:53
static void DestroyBroker(string Key)
Destroys a broker object instance
Definition: XmppBrokers.cs:85
Node representing a roster item in the roster of an XMPP account.
Node representing an XMPP broker.
bool TrustServer
If broker server should be trusted
ISniffer[] Sniffers
Registered sniffers.
async Task Warning(string Warning)
Called to inform the viewer of a warning state.
override async Task AddAsync(INode Child)
Adds a new child to the node.
string PasswordMechanism
Password authentication mechanism
async override Task< IEnumerable< Parameter > > GetDisplayableParametersAsync(Language Language, RequestOrigin Caller)
Gets displayable parameters.
async Task ReceiveBinary(DateTime Timestamp, byte[] Data)
Called when binary data has been received.
override Task< IEnumerable< ICommand > > Commands
Available command objects. If no commands are available, null is returned.
async Task Exception(string Exception)
Called to inform the viewer of an exception state.
bool AllowInsecureMechanisms
If insecure authentication mechanisms should be trusted
bool Remove(ISniffer Sniffer)
ICommunicationLayer.Remove
void Add(ISniffer Sniffer)
ICommunicationLayer.Add
async Task ReceiveText(string Text)
Called when text has been received.
override Task< string > GetTypeNameAsync(Language Language)
Gets the type name of the node.
override async Task< bool > RemoveAsync(INode Child)
Removes a child from the node.
async Task ReceiveBinary(byte[] Data)
Called when binary data has been received.
bool DecoupledEvents
If events raised from the communication layer are decoupled, i.e. executed in parallel with the sourc...
async Task Information(string Comment)
Called to inform the viewer of something.
async Task ReceiveText(DateTime Timestamp, string Text)
Called when text has been received.
void AddRange(IEnumerable< ISniffer > Sniffers)
ICommunicationLayer.AddRange
async Task Exception(DateTime Timestamp, string Exception)
Called to inform the viewer of an exception state.
async Task Exception(Exception Exception)
Called to inform the viewer of an exception state.
override Task NodeUpdated()
Persists changes to the node, and generates a node updated event.
IEnumerator< ISniffer > GetEnumerator()
IEnumerable<ISniffer>.GetEnumerator
async Task TransmitBinary(byte[] Data)
Called when binary data has been transmitted.
async Task Error(string Error)
Called to inform the viewer of an error state.
override Task< bool > AcceptsChildAsync(INode Child)
If the node accepts a presumptive child, i.e. can receive as a child (if that child accepts the node ...
async Task Warning(DateTime Timestamp, string Warning)
Called to inform the viewer of a warning state.
string AutoAcceptPattern
Partition ID
XmppBrokerNode()
Node representing an XMPP broker.
async Task Exception(DateTime Timestamp, Exception Exception)
Called to inform the viewer of an exception state.
string Key
Key representing the node.
async Task TransmitBinary(DateTime Timestamp, byte[] Data)
Called when binary data has been transmitted.
override Task DestroyAsync()
Destroys the node. If it is a child to a parent node, it is removed from the parent first.
async Task TransmitText(DateTime Timestamp, string Text)
Called when text has been transmitted.
async Task< RosterItemNode > GetRosterItem(string BareJID, bool CreateIfNotExists)
Gets a roster item.
async Task TransmitText(string Text)
Called when text has been transmitted.
bool HasSniffers
If there are sniffers registered on the object.
async Task< IEnumerable< ICommand > > GetCommands()
Gets available commands.
async Task Information(DateTime Timestamp, string Comment)
Called to inform the viewer of something.
async Task Error(DateTime Timestamp, string Error)
Called to inform the viewer of an error state.
Abstract base class for XMPP Extensions.
Interface for observable classes implementing communication protocols.
Interface for sniffers. Sniffers can be added to ICommunicationLayer classes to eavesdrop on communic...
Definition: ISniffer.cs:11
Interface for nodes that are published through the concentrator interface.
Definition: INode.cs:49
Task< IEnumerable< INode > > ChildNodes
Child nodes. If no child nodes are available, null is returned.
Definition: INode.cs:140