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;
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 [Encrypted(32)]
63 public string Password
64 {
65 get => this.password;
66 set => this.password = value;
67 }
68
72 public string[] EncryptedProperties => new string[] { nameof(this.Password) };
73
77 [Page(2, "XMPP")]
78 [Header(17, "Password Hash Mechanism:")]
79 [ToolTip(18, "Mechanism used for password hash.")]
80 [DefaultValueStringEmpty]
81 public string PasswordMechanism
82 {
83 get => this.passwordMechanism;
84 set => this.passwordMechanism = value;
85 }
86
90 [Page(2, "XMPP")]
91 [Header(19, "Trust Server Certificate")]
92 [ToolTip(20, "If the server certificate should be trusted, even if it does not validate.")]
93 [DefaultValue(false)]
94 public bool TrustServer
95 {
96 get => this.trustServer;
97 set => this.trustServer = value;
98 }
99
103 [Page(2, "XMPP")]
104 [Header(21, "Allow Insecure Mechanisms")]
105 [ToolTip(22, "If insecure mechanisms are permitted during authentication.")]
106 [DefaultValue(false)]
108 {
109 get => this.allowInsecureMechanisms;
110 set => this.allowInsecureMechanisms = value;
111 }
112
116 [Page(28, "Roster", 110)]
117 [Header(32, "Auto-accept Pattern:")]
118 [ToolTip(33, "If a presence subscription comes from a JID that matches this regular expression, it will be automatically accepted.")]
119 public string AutoAcceptPattern { get; set; }
120
126 public override Task<string> GetTypeNameAsync(Language Language)
127 {
128 return Language.GetStringAsync(typeof(XmppBrokerNode), 23, "XMPP Broker");
129 }
130
136 public override Task<bool> AcceptsChildAsync(INode Child)
137 {
138 return Task.FromResult(
139 Child is ConcentratorNode ||
140 Child is ConcentratorSourceNode ||
141 Child is ConcentratorPartitionNode ||
142 Child is ConcentratorDevice ||
143 Child is RosterItemNode ||
144 Child is XmppExtensionNode);
145 }
146
150 public override Task DestroyAsync()
151 {
152 if (!string.IsNullOrEmpty(this.brokerKey))
153 XmppBrokers.DestroyBroker(this.brokerKey);
154
155 return base.DestroyAsync();
156 }
157
161 [IgnoreMember]
162 public string Key
163 {
164 get
165 {
166 string PrevKey = this.brokerKey;
167 this.brokerKey = XmppBrokers.GetKey(this.Host, this.Port, this.Tls, this.userName, this.password, this.passwordMechanism);
168
169 if (PrevKey != this.brokerKey && !string.IsNullOrEmpty(PrevKey))
170 XmppBrokers.DestroyBroker(PrevKey);
171
172 return this.brokerKey;
173 }
174 }
175
179 protected override Task NodeUpdated()
180 {
181 this.GetBroker();
182
183 return base.NodeUpdated();
184 }
185
186 internal XmppBroker GetCachedBroker()
187 {
188 return XmppBrokers.GetCachedBroker(this.Key);
189 }
190
191 internal Task<XmppBroker> GetBroker()
192 {
193 return XmppBrokers.GetBroker(this, this.Key, this.Host, this.Port, this.Tls, this.userName, this.password,
194 this.passwordMechanism, this.trustServer, this.allowInsecureMechanisms);
195 }
196
197 #region ICommunicationLayer
198
203 public bool DecoupledEvents => true;
204
208 public void Add(ISniffer Sniffer)
209 {
210 this.GetBroker().Result?.Client?.Add(Sniffer);
211 }
212
216 public void AddRange(IEnumerable<ISniffer> Sniffers)
217 {
218 this.GetBroker().Result?.Client?.AddRange(Sniffers);
219 }
220
224 public bool Remove(ISniffer Sniffer)
225 {
226 return this.GetBroker().Result?.Client?.Remove(Sniffer) ?? false;
227 }
228
233 {
234 get { return this.GetBroker().Result?.Client?.Sniffers ?? Array.Empty<ISniffer>(); }
235 }
236
240 public bool HasSniffers
241 {
242 get { return this.GetBroker().Result?.Client?.HasSniffers ?? false; }
243 }
244
248 public IEnumerator<ISniffer> GetEnumerator()
249 {
250 return new SnifferEnumerator(this.Sniffers);
251 }
252
253 IEnumerator IEnumerable.GetEnumerator()
254 {
255 return this.GetBroker().Result?.Client?.GetEnumerator() ?? Array.Empty<ISniffer>().GetEnumerator();
256 }
257
262 public void ReceiveBinary(int Count) => this.GetCachedBroker()?.Client?.ReceiveBinary(Count);
263
270 public void ReceiveBinary(bool ConstantBuffer, byte[] Data) => this.GetCachedBroker()?.Client?.ReceiveBinary(ConstantBuffer, Data);
271
280 public void ReceiveBinary(bool ConstantBuffer, byte[] Data, int Offset, int Count) => this.GetCachedBroker()?.Client?.ReceiveBinary(ConstantBuffer, Data, Offset, Count);
281
286 public void TransmitBinary(int Count) => this.GetCachedBroker()?.Client?.TransmitBinary(Count);
287
294 public void TransmitBinary(bool ConstantBuffer, byte[] Data) => this.GetCachedBroker()?.Client?.TransmitBinary(ConstantBuffer, Data);
295
304 public void TransmitBinary(bool ConstantBuffer, byte[] Data, int Offset, int Count) => this.GetCachedBroker()?.Client?.TransmitBinary(ConstantBuffer, Data, Offset, Count);
305
310 public void ReceiveText(string Text) => this.GetCachedBroker()?.Client?.ReceiveText(Text);
311
316 public void TransmitText(string Text) => this.GetCachedBroker()?.Client?.TransmitText(Text);
317
322 public void Information(string Comment) => this.GetCachedBroker()?.Client?.Information(Comment);
323
328 public void Warning(string Warning) => this.GetCachedBroker()?.Client?.Warning(Warning);
329
334 public void Error(string Error) => this.GetCachedBroker()?.Client?.Error(Error);
335
340 public void Exception(Exception Exception) => this.GetCachedBroker()?.Client?.Exception(Exception);
341
346 public void Exception(string Exception) => this.GetCachedBroker()?.Client?.Exception(Exception);
347
353 public void ReceiveBinary(DateTime Timestamp, int Count) => this.GetCachedBroker()?.Client?.ReceiveBinary(Timestamp, Count);
354
362 public void ReceiveBinary(DateTime Timestamp, bool ConstantBuffer, byte[] Data) => this.GetCachedBroker()?.Client?.ReceiveBinary(Timestamp, ConstantBuffer, Data);
363
373 public void ReceiveBinary(DateTime Timestamp, bool ConstantBuffer, byte[] Data, int Offset, int Count) => this.GetCachedBroker()?.Client?.ReceiveBinary(Timestamp, ConstantBuffer, Data, Offset, Count);
374
380 public void TransmitBinary(DateTime Timestamp, int Count) => this.GetCachedBroker()?.Client?.TransmitBinary(Timestamp, Count);
381
389 public void TransmitBinary(DateTime Timestamp, bool ConstantBuffer, byte[] Data) => this.GetCachedBroker()?.Client?.TransmitBinary(Timestamp, ConstantBuffer, Data);
390
400 public void TransmitBinary(DateTime Timestamp, bool ConstantBuffer, byte[] Data, int Offset, int Count) => this.GetCachedBroker()?.Client?.TransmitBinary(Timestamp, ConstantBuffer, Data, Offset, Count);
401
407 public void ReceiveText(DateTime Timestamp, string Text) => this.GetCachedBroker()?.Client?.ReceiveText(Timestamp, Text);
408
414 public void TransmitText(DateTime Timestamp, string Text) => this.GetCachedBroker()?.Client?.TransmitText(Timestamp, Text);
415
421 public void Information(DateTime Timestamp, string Comment) => this.GetCachedBroker()?.Client?.Information(Timestamp, Comment);
422
428 public void Warning(DateTime Timestamp, string Warning) => this.GetCachedBroker()?.Client?.Warning(Timestamp, Warning);
429
435 public void Error(DateTime Timestamp, string Error) => this.GetCachedBroker()?.Client?.Error(Timestamp, Error);
436
442 public void Exception(DateTime Timestamp, string Exception) => this.GetCachedBroker()?.Client?.Exception(Timestamp, Exception);
443
449 public void Exception(DateTime Timestamp, Exception Exception) => this.GetCachedBroker()?.Client?.Exception(Timestamp, Exception);
450
451 #endregion
452
456 public override Task<IEnumerable<ICommand>> Commands => this.GetCommands();
457
462 public async Task<IEnumerable<ICommand>> GetCommands()
463 {
464 List<ICommand> Result = new List<ICommand>();
465
466 Result.AddRange(await base.Commands);
467 Result.Add(new ReconnectCommand((await this.GetBroker()).Client));
468
469 return Result;
470 }
471
478 public async override Task<IEnumerable<Parameter>> GetDisplayableParametersAsync(Language Language, RequestOrigin Caller)
479 {
480 LinkedList<Parameter> Result = await base.GetDisplayableParametersAsync(Language, Caller) as LinkedList<Parameter>;
481 XmppBroker Broker = await this.GetBroker();
482
483 Result.AddLast(new StringParameter("State", await Language.GetStringAsync(typeof(XmppBrokerNode), 27, "State"),
484 Broker.Client.State.ToString() ?? string.Empty));
485
486 return Result;
487 }
488
489 #region Roster
490
497 public async Task<RosterItemNode> GetRosterItem(string BareJID, bool CreateIfNotExists)
498 {
499 RosterItemNode Result;
500 bool Load;
501
502 lock (this.roster)
503 {
504 if (this.roster.TryGetValue(BareJID, out Result))
505 return Result;
506
507 Load = this.roster.Count == 0;
508 }
509
510 if (Load)
511 {
512 IEnumerable<INode> Children = await this.ChildNodes;
513
514 lock (this.roster)
515 {
516 foreach (INode Node in Children)
517 {
518 if (Node is RosterItemNode RosterItem)
519 this.roster[RosterItem.BareJID] = RosterItem;
520 }
521
522 if (this.roster.TryGetValue(BareJID, out Result))
523 return Result;
524 }
525 }
526
527 if (CreateIfNotExists)
528 {
529 Result = new RosterItemNode()
530 {
531 NodeId = await GetUniqueNodeId(this.NodeId + ", " + BareJID),
532 BareJID = BareJID
533 };
534
535 await this.AddAsync(Result);
536
537 return Result;
538 }
539 else
540 return null;
541 }
542
547 public override async Task AddAsync(INode Child)
548 {
549 await base.AddAsync(Child);
550
551 if (Child is RosterItemNode Item)
552 {
553 lock (this.roster)
554 {
555 this.roster[Item.BareJID] = Item;
556 }
557 }
558
559 if (Child is XmppExtensionNode Extension)
560 {
561 try
562 {
563 XmppBroker Broker = await this.GetBroker();
564 XmppClient Client = Broker.Client;
565
566 if (!Extension.IsRegisteredExtension(Client))
567 await Extension.RegisterExtension(Client);
568 }
569 catch (Exception ex)
570 {
571 await this.LogErrorAsync(ex.Message);
572 }
573 }
574 }
575
581 public override async Task<bool> RemoveAsync(INode Child)
582 {
583 if (!await base.RemoveAsync(Child))
584 return false;
585
586 if (Child is RosterItemNode Item)
587 {
588 lock (this.roster)
589 {
590 this.roster.Remove(Item.BareJID);
591 }
592 }
593
594 if (Child is XmppExtensionNode Extension)
595 {
596 try
597 {
598 XmppBroker Broker = await this.GetBroker();
599 XmppClient Client = Broker.Client;
600
601 if (Extension.IsRegisteredExtension(Client))
602 await Extension.UnregisterExtension(Client);
603 }
604 catch (Exception ex)
605 {
606 await this.LogErrorAsync(ex.Message);
607 }
608 }
609
610 return true;
611 }
612
613 #endregion
614
615 }
616}
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:58
XmppState State
Current state of connection.
Definition: XmppClient.cs:985
bool UnregisterExtension(IXmppExtension Extension)
Unregisters an extension on the client.
Definition: XmppClient.cs:7363
void RegisterExtension(IXmppExtension Extension)
Registers an extension with the client.
Definition: XmppClient.cs:7349
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:73
Node representing a port on an IP Host machine.
Definition: IpHostPort.cs:24
bool Tls
If connection is encrypted using TLS or not.
Definition: IpHostPort.cs:70
int Port
Port number.
Definition: IpHostPort.cs:58
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 XmppBroker GetCachedBroker(string Key)
Gets an XMPP broker object instance, if available in the cache.
Definition: XmppBrokers.cs:44
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:69
static void DestroyBroker(string Key)
Destroys a broker object instance
Definition: XmppBrokers.cs:101
Node representing a roster item in the roster of an XMPP account.
Node representing an XMPP broker.
void TransmitText(string Text)
Called when text has been transmitted.
void Exception(DateTime Timestamp, Exception Exception)
Called to inform the viewer of an exception state.
bool TrustServer
If broker server should be trusted
void Warning(DateTime Timestamp, string Warning)
Called to inform the viewer of a warning state.
void TransmitBinary(DateTime Timestamp, bool ConstantBuffer, byte[] Data)
Called when binary data has been transmitted.
void Warning(string Warning)
Called to inform the viewer of a warning state.
void ReceiveBinary(bool ConstantBuffer, byte[] Data, int Offset, int Count)
Called when binary data has been received.
ISniffer[] Sniffers
Registered sniffers.
void TransmitText(DateTime Timestamp, string Text)
Called when text has been transmitted.
override async Task AddAsync(INode Child)
Adds a new child to the node.
void TransmitBinary(int Count)
Called when binary data has been transmitted.
string PasswordMechanism
Password authentication mechanism
async override Task< IEnumerable< Parameter > > GetDisplayableParametersAsync(Language Language, RequestOrigin Caller)
Gets displayable parameters.
override Task< IEnumerable< ICommand > > Commands
Available command objects. If no commands are available, null is returned.
void ReceiveText(string Text)
Called when text has been received.
bool AllowInsecureMechanisms
If insecure authentication mechanisms should be trusted
bool Remove(ISniffer Sniffer)
ICommunicationLayer.Remove
void Error(string Error)
Called to inform the viewer of an error state.
void ReceiveBinary(int Count)
Called when binary data has been received.
void Add(ISniffer Sniffer)
ICommunicationLayer.Add
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.
void ReceiveText(DateTime Timestamp, string Text)
Called when text has been received.
void TransmitBinary(DateTime Timestamp, int Count)
Called when binary data has been transmitted.
bool DecoupledEvents
If events raised from the communication layer are decoupled, i.e. executed in parallel with the sourc...
void Exception(Exception Exception)
Called to inform the viewer of an exception state.
void ReceiveBinary(DateTime Timestamp, int Count)
Called when binary data has been received.
void TransmitBinary(bool ConstantBuffer, byte[] Data)
Called when binary data has been transmitted.
void TransmitBinary(bool ConstantBuffer, byte[] Data, int Offset, int Count)
Called when binary data has been transmitted.
string[] EncryptedProperties
Array of properties that are encrypted.
void AddRange(IEnumerable< ISniffer > Sniffers)
ICommunicationLayer.AddRange
override Task NodeUpdated()
Persists changes to the node, and generates a node updated event.
void Exception(string Exception)
Called to inform the viewer of an exception state.
void ReceiveBinary(DateTime Timestamp, bool ConstantBuffer, byte[] Data, int Offset, int Count)
Called when binary data has been received.
void Error(DateTime Timestamp, string Error)
Called to inform the viewer of an error state.
IEnumerator< ISniffer > GetEnumerator()
IEnumerable<ISniffer>.GetEnumerator
void ReceiveBinary(bool ConstantBuffer, byte[] Data)
Called when binary data has been received.
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 ...
void Exception(DateTime Timestamp, string Exception)
Called to inform the viewer of an exception state.
string AutoAcceptPattern
Partition ID
XmppBrokerNode()
Node representing an XMPP broker.
void Information(string Comment)
Called to inform the viewer of something.
string Key
Key representing the node.
void Information(DateTime Timestamp, string Comment)
Called to inform the viewer of something.
override Task DestroyAsync()
Destroys the node. If it is a child to a parent node, it is removed from the parent first.
async Task< RosterItemNode > GetRosterItem(string BareJID, bool CreateIfNotExists)
Gets a roster item.
bool HasSniffers
If there are sniffers registered on the object.
async Task< IEnumerable< ICommand > > GetCommands()
Gets available commands.
void TransmitBinary(DateTime Timestamp, bool ConstantBuffer, byte[] Data, int Offset, int Count)
Called when binary data has been transmitted.
void ReceiveBinary(DateTime Timestamp, bool ConstantBuffer, byte[] Data)
Called when binary data has been received.
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:10
Interface for objects containing encrypted properties. Mark the properties that are encrypted with th...
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