Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
Component.cs
1using System;
3using System.Text;
4using System.Threading.Tasks;
5using System.Xml;
7using Waher.Events;
10
12{
17 {
21 protected SortedDictionary<string, bool> features = new SortedDictionary<string, bool>();
22
26 protected readonly object synchObject = new object();
27
28 private readonly Dictionary<string, EventHandlerAsync<IqEventArgs>> iqGetHandlers = new Dictionary<string, EventHandlerAsync<IqEventArgs>>();
29 private readonly Dictionary<string, EventHandlerAsync<IqEventArgs>> iqSetHandlers = new Dictionary<string, EventHandlerAsync<IqEventArgs>>();
30 private readonly Dictionary<string, EventHandlerAsync<MessageEventArgs>> messageHandlers = new Dictionary<string, EventHandlerAsync<MessageEventArgs>>();
31 private readonly Dictionary<string, EventHandlerAsync<PresenceEventArgs>> presenceHandlers = new Dictionary<string, EventHandlerAsync<PresenceEventArgs>>();
32 private readonly IqResponses responses = new IqResponses(TimeSpan.FromMinutes(1), TimeSpan.FromSeconds(10));
33 private readonly XmppServer server;
34 private readonly CaseInsensitiveString subdomain;
35 private readonly CaseInsensitiveString subdomainSuffixed;
36 private readonly XmppAddress mainDomain;
37 private readonly string name;
38
45 public Component(XmppServer Server, string Subdomain, string Name)
47 {
48 }
49
57 {
58 this.subdomain = Subdomain;
59 this.subdomainSuffixed = Subdomain + ".";
60 this.name = Name;
61 this.server = Server;
62 this.mainDomain = new XmppAddress(this.subdomainSuffixed + this.server.Domain);
63
64 if (!string.IsNullOrEmpty(Subdomain) && !(this.server is null))
65 {
66 if (!this.server.RegisterComponent(this))
67 throw new InvalidOperationException("A component with subdomain " + Subdomain + " has already been registered.");
68 }
69
70 this.RegisterIqGetHandler("query", XmppServer.DiscoveryNamespace, this.DiscoveryQueryGet, true); // XEP-0030
71 this.RegisterIqGetHandler("query", XmppServer.DiscoveryItemsNamespace, this.DiscoveryQueryItemsGet, true); // XEP-0030
72 }
73
77 public CaseInsensitiveString Subdomain => this.subdomain;
78
82 public CaseInsensitiveString SubdomainSuffixed => this.subdomainSuffixed;
83
87 public XmppAddress MainDomain => this.mainDomain;
88
92 public string Name => this.name;
93
97 public XmppServer Server => this.server;
98
102 public virtual void Dispose()
103 {
104 if (!string.IsNullOrEmpty(this.subdomain) && !(this.server is null))
105 this.server.UnregisterComponent(this);
106
107 this.UnregisterIqGetHandler("query", XmppServer.DiscoveryNamespace, this.DiscoveryQueryGet, true); // XEP-0030
108
109 this.responses.Dispose();
110 }
111
116 public virtual bool SupportsAccounts => false;
117
124 public bool IsComponentDomain(CaseInsensitiveString Domain, bool IncludeAlternativeDomains)
125 {
126 if (Domain == this.subdomainSuffixed + this.server.Domain)
127 return true;
128
129 if (IncludeAlternativeDomains && !(this.server.AlternativeDomains is null))
130 {
131 foreach (CaseInsensitiveString s in this.server.AlternativeDomains)
132 {
133 if (Domain == this.subdomainSuffixed + s)
134 return true;
135 }
136 }
137
138 return false;
139 }
140
141 #region Stanzas
142
150 public void RegisterIqGetHandler(string LocalName, string Namespace, EventHandlerAsync<IqEventArgs> Handler, bool PublishNamespaceAsFeature)
151 {
152 this.RegisterIqHandler(this.iqGetHandlers, LocalName, Namespace, Handler, PublishNamespaceAsFeature);
153 }
154
162 public void RegisterIqSetHandler(string LocalName, string Namespace, EventHandlerAsync<IqEventArgs> Handler, bool PublishNamespaceAsFeature)
163 {
164 this.RegisterIqHandler(this.iqSetHandlers, LocalName, Namespace, Handler, PublishNamespaceAsFeature);
165 }
166
167 private void RegisterIqHandler(Dictionary<string, EventHandlerAsync<IqEventArgs>> Handlers, string LocalName, string Namespace, EventHandlerAsync<IqEventArgs> Handler,
168 bool PublishNamespaceAsFeature)
169 {
170 string Key = LocalName + " " + Namespace;
171
172 lock (this.synchObject)
173 {
174 if (Handlers.ContainsKey(Key))
175 throw new ArgumentException("Handler already registered.", nameof(LocalName));
176
177 Handlers[Key] = Handler;
178
179 if (PublishNamespaceAsFeature)
180 this.features[Namespace] = true;
181 }
182 }
183
191 public void RegisterMessageHandler(string LocalName, string Namespace, EventHandlerAsync<MessageEventArgs> Handler, bool PublishNamespaceAsFeature)
192 {
193 string Key = LocalName + " " + Namespace;
194
195 lock (this.synchObject)
196 {
197 if (this.messageHandlers.ContainsKey(Key))
198 throw new ArgumentException("Handler already registered.", nameof(LocalName));
199
200 this.messageHandlers[Key] = Handler;
201
202 if (PublishNamespaceAsFeature)
203 this.features[Namespace] = true;
204 }
205 }
206
214 public void RegisterPresenceHandler(string LocalName, string Namespace, EventHandlerAsync<PresenceEventArgs> Handler, bool PublishNamespaceAsFeature)
215 {
216 string Key = LocalName + " " + Namespace;
217
218 lock (this.synchObject)
219 {
220 if (this.presenceHandlers.ContainsKey(Key))
221 throw new ArgumentException("Handler already registered.", nameof(LocalName));
222
223 this.presenceHandlers[Key] = Handler;
224
225 if (PublishNamespaceAsFeature)
226 this.features[Namespace] = true;
227 }
228 }
229
234 public void RegisterFeature(string Namespace)
235 {
236 lock (this.synchObject)
237 {
238 this.features[Namespace] = true;
239 }
240 }
241
250 public bool UnregisterIqGetHandler(string LocalName, string Namespace, EventHandlerAsync<IqEventArgs> Handler, bool RemoveNamespaceAsFeature)
251 {
252 return this.UnregisterIqHandler(this.iqGetHandlers, LocalName, Namespace, Handler, RemoveNamespaceAsFeature);
253 }
254
263 public bool UnregisterIqSetHandler(string LocalName, string Namespace, EventHandlerAsync<IqEventArgs> Handler, bool RemoveNamespaceAsFeature)
264 {
265 return this.UnregisterIqHandler(this.iqSetHandlers, LocalName, Namespace, Handler, RemoveNamespaceAsFeature);
266 }
267
268 private bool UnregisterIqHandler(Dictionary<string, EventHandlerAsync<IqEventArgs>> Handlers, string LocalName, string Namespace, EventHandlerAsync<IqEventArgs> Handler,
269 bool RemoveNamespaceAsFeature)
270 {
271 string Key = LocalName + " " + Namespace;
272
273 lock (this.synchObject)
274 {
275 if (!Handlers.TryGetValue(Key, out EventHandlerAsync<IqEventArgs> h))
276 return false;
277
278 if (h != Handler)
279 return false;
280
281 Handlers.Remove(Key);
282
283 if (RemoveNamespaceAsFeature)
284 this.features.Remove(Namespace);
285 }
286
287 return true;
288 }
289
298 public bool UnregisterMessageHandler(string LocalName, string Namespace, EventHandlerAsync<MessageEventArgs> Handler, bool RemoveNamespaceAsFeature)
299 {
300 string Key = LocalName + " " + Namespace;
301
302 lock (this.synchObject)
303 {
304 if (!this.messageHandlers.TryGetValue(Key, out EventHandlerAsync<MessageEventArgs> h))
305 return false;
306
307 if (h != Handler)
308 return false;
309
310 this.messageHandlers.Remove(Key);
311
312 if (RemoveNamespaceAsFeature)
313 this.features.Remove(Namespace);
314 }
315
316 return true;
317 }
318
327 public bool UnregisterPresenceHandler(string LocalName, string Namespace, EventHandlerAsync<PresenceEventArgs> Handler, bool RemoveNamespaceAsFeature)
328 {
329 string Key = LocalName + " " + Namespace;
330
331 lock (this.synchObject)
332 {
333 if (!this.presenceHandlers.TryGetValue(Key, out EventHandlerAsync<PresenceEventArgs> h))
334 return false;
335
336 if (h != Handler)
337 return false;
338
339 this.presenceHandlers.Remove(Key);
340
341 if (RemoveNamespaceAsFeature)
342 this.features.Remove(Namespace);
343 }
344
345 return true;
346 }
347
352 public void UnregisterFeature(string Namespace)
353 {
354 lock (this.synchObject)
355 {
356 this.features.Remove(Namespace);
357 }
358 }
359
370 public async Task<bool> IQ(string Type, string Id, XmppAddress To, XmppAddress From, string Language, Stanza Stanza, ISender Sender)
371 {
372 Dictionary<string, EventHandlerAsync<IqEventArgs>> Handlers;
373 EventHandlerAsync<IqEventArgs> h = null;
374 IqResponse Response;
375 string Counter;
376 string Key;
377
378 switch (Type)
379 {
380 case "get":
381 if (this.responses.TryGet(From.Address, Id, true, out Response, out bool Created))
382 {
383 if (!Created)
384 {
385 KeyValuePair<string, bool> P = await Response.GetResponse();
386
387 if (P.Value)
388 return await Sender.IqResult(Id, From, To, P.Key);
389 else
390 return await Sender.IqError(Id, From, To, P.Key);
391 }
392 }
393
394 Handlers = this.iqGetHandlers;
395 Counter = "XMPP.Component." + this.subdomain + ".Get";
396 break;
397
398 case "set":
399 if (this.responses.TryGet(From.Address, Id, true, out Response, out Created))
400 {
401 if (!Created)
402 {
403 KeyValuePair<string, bool> P = await Response.GetResponse();
404
405 if (P.Value)
406 return await Sender.IqResult(Id, From, To, P.Key);
407 else
408 return await Sender.IqError(Id, From, To, P.Key);
409 }
410 }
411
412 Handlers = this.iqSetHandlers;
413 Counter = "XMPP.Component." + this.subdomain + ".Set";
414 break;
415
416 case "result":
417 case "error":
418 return await this.server.ProcessResponse(Type, Id, To, From, Language, true, false, Stanza, Sender);
419
420 default:
421 if (Sender is null)
422 return false;
423 else
424 return !(await Sender.IqErrorBadRequest(Id, From, To, "Invalid type.", "en") is null);
425 }
426
427 IqEventArgs e = new IqEventArgs(Sender, Stanza.StanzaElement, Id, Type, To, From, Language, Response);
428
429 lock (this.synchObject)
430 {
431 foreach (XmlNode N in Stanza.StanzaElement.ChildNodes)
432 {
433 if (!(N is XmlElement E))
434 continue;
435
436 Key = E.LocalName + " " + E.NamespaceURI;
437 if (Handlers.TryGetValue(Key, out h))
438 {
439 Counter += "." + E.LocalName;
440 e.Query = E;
441 break;
442 }
443 else
444 h = null;
445 }
446 }
447
448 if (h is null)
449 {
450 if (Sender is null)
451 {
452 Response.SetResult(string.Empty, false);
453 return false;
454 }
455 else
456 {
457 string ErrorXml = await Sender.IqError(Id, From, To, "cancel", "<feature-not-implemented xmlns='" + XmppServer.StanzaNamespace + "'/>", string.Empty, string.Empty);
458 Response.SetResult(ErrorXml, false);
459 return !(ErrorXml is null);
460 }
461 }
462
463 try
464 {
465 await RuntimeCounters.IncrementCounter(Counter);
466 await h(this, e);
467 return true;
468 }
469 catch (Exception ex)
470 {
471 if (Sender is null)
472 {
473 Response.SetResult(string.Empty, false);
474 return false;
475 }
476 else
477 {
478 string ErrorXml = await Sender.IqError(Id, From, To, ex);
479 Response.SetResult(ErrorXml, false);
480 return !(ErrorXml is null);
481 }
482 }
483 }
484
495 public Task<bool> IQ(string Type, string Id, XmppAddress To, XmppAddress From, string Language, string ContentXml, ISender Sender)
496 {
497 return this.IQ(Type, Id, To, From, Language, XmppServer.ToStanza("iq", Type, Id, To, From, Language, ContentXml), Sender);
498 }
499
510 public async Task<bool> Message(string Type, string Id, XmppAddress To, XmppAddress From, string Language, Stanza Stanza, ISender Sender)
511 {
512 MessageEventArgs e = new MessageEventArgs(Sender, Stanza.StanzaElement, Id, Type, To, From, Language);
513 EventHandlerAsync<MessageEventArgs> h = null;
514 string Counter = "XMPP.Component." + this.subdomain + ".Message";
515 string Key;
516
517 lock (this.synchObject)
518 {
519 foreach (XmlNode N in Stanza.StanzaElement.ChildNodes)
520 {
521 if (!(N is XmlElement E))
522 continue;
523
524 Key = E.LocalName + " " + E.NamespaceURI;
525 if (this.messageHandlers.TryGetValue(Key, out h))
526 {
527 Counter += "." + E.LocalName;
528 e.Content = E;
529 break;
530 }
531 else
532 h = null;
533 }
534 }
535
536 try
537 {
538 if (h is null)
539 await this.MessageNoHandlerReceived(e);
540 else
541 {
542 await RuntimeCounters.IncrementCounter(Counter);
543 await h(this, e);
544 }
545 }
546 catch (Exception ex)
547 {
548 if (!(Sender is null))
549 await (Sender?.MessageError(Id, From, To, ex) ?? Task.CompletedTask);
550 }
551
552 return true;
553 }
554
560 {
561 return Task.CompletedTask;
562 }
563
574 public Task<bool> Message(string Type, string Id, XmppAddress To, XmppAddress From, string Language, string ContentXml, ISender Sender)
575 {
576 return this.Message(Type, Id, To, From, Language, XmppServer.ToStanza("message", Type, Id, To, From, Language, ContentXml), Sender);
577 }
578
588 //public Task<bool> Presence(string Type, string Id, CaseInsensitiveString From, string Language, Stanza Stanza, ISender Sender)
589 //{
590 // // TODO: Component presence
591 // return Task.FromResult(true);
592 //}
593
604 public async Task<bool> Presence(string Type, string Id, XmppAddress To, XmppAddress From, string Language, Stanza Stanza, ISender Sender)
605 {
606 PresenceEventArgs e = new PresenceEventArgs(Sender, Type, Id, To, From, Language, Stanza, null);
607 EventHandlerAsync<PresenceEventArgs> h = null;
608 string Counter = "XMPP.Component." + this.subdomain + ".Presence";
609 string Key;
610
611 lock (this.synchObject)
612 {
613 foreach (XmlNode N in Stanza.StanzaElement.ChildNodes)
614 {
615 if (!(N is XmlElement E))
616 continue;
617
618 Key = E.LocalName + " " + E.NamespaceURI;
619 if (this.presenceHandlers.TryGetValue(Key, out h))
620 {
621 Counter += "." + E.LocalName;
622 e.Content = E;
623 break;
624 }
625 else
626 h = null;
627 }
628 }
629
630 try
631 {
632 if (h is null)
633 await this.PresenceNoHandlerReceived(e);
634 else
635 {
636 await RuntimeCounters.IncrementCounter(Counter);
637 await h(this, e);
638 }
639 }
640 catch (Exception ex)
641 {
642 if (!(Sender is null))
643 await (Sender?.PresenceError(Id, From, To, ex) ?? Task.CompletedTask);
644 }
645
646 return true;
647 }
648
654 {
655 return Task.CompletedTask;
656 }
657
668 public Task<bool> Presence(string Type, string Id, XmppAddress To, XmppAddress From, string Language, string ContentXml, ISender Sender)
669 {
670 return this.Presence(Type, Id, To, From, Language, XmppServer.ToStanza("presence", Type, Id, To, From, Language, ContentXml), Sender);
671 }
672
678 protected static string InnerXmlNoJabberNamespace(XmlElement Xml)
679 {
680 if (Xml is null)
681 return string.Empty;
682
683 string s = Xml.OuterXml;
684 int i = s.IndexOf('>');
685 int j = s.LastIndexOf('<');
686
687 if (j <= i)
688 return string.Empty;
689
690 return s.Substring(i + 1, j - i - 1);
691 }
692
693 #endregion
694
695 #region Discovery XEP-0030
696
702 protected virtual async Task DiscoveryQueryGet(object Sender, IqEventArgs e)
703 {
704 XmlElement E = e.Query;
705
706 if (e.To.HasAccount && (!this.SupportsAccounts || !await this.SupportsAccount(e.To.Account)))
707 {
708 await e.IqErrorItemNotFound(e.To, "Item not found.", "en");
709 return;
710 }
711
712 string Node = XML.Attribute(E, "node");
713 if (!string.IsNullOrEmpty(Node) && !await this.SupportsNode(Node))
714 {
715 await e.IqErrorItemNotFound(e.To, "Node not found.", "en");
716 return;
717 }
718
719 StringBuilder Xml = new StringBuilder();
720
721 Xml.Append("<query xmlns='");
722 Xml.Append(XmppServer.DiscoveryNamespace);
723 Xml.Append("'>");
724
725 await this.AppendServiceDiscoveryIdentities(Xml, e, Node);
726
727 if (string.IsNullOrEmpty(e.To.Account) && string.IsNullOrEmpty(Node))
728 {
729 lock (this.synchObject)
730 {
731 foreach (string Feature in this.features.Keys)
732 {
733 Xml.Append("<feature var='");
734 Xml.Append(XML.Encode(Feature));
735 Xml.Append("'/>");
736 }
737 }
738 }
739
740 await this.AppendServiceDiscoveryFeatures(Xml, e, Node);
741
742 Xml.Append("</query>");
743
744 await e.IqResult(Xml.ToString(), e.To);
745 }
746
752 protected virtual Task<bool> SupportsAccount(string Account)
753 {
754 return Task.FromResult(false);
755 }
756
762 protected virtual Task<bool> SupportsNode(string Node)
763 {
764 return Task.FromResult(false);
765 }
766
772 protected virtual async Task DiscoveryQueryItemsGet(object Sender, IqEventArgs e)
773 {
774 XmlElement E = e.Query;
775
776 if (e.To.HasAccount && (!this.SupportsAccounts || !await this.SupportsAccount(e.To.Account)))
777 {
778 await e.IqErrorItemNotFound(e.To, "Item not found.", "en");
779 return;
780 }
781
782 string Node = XML.Attribute(E, "node");
783 if (!string.IsNullOrEmpty(Node) && !await this.SupportsNode(Node))
784 {
785 await e.IqErrorItemNotFound(e.To, "Node not found.", "en");
786 return;
787 }
788
789 StringBuilder Xml = new StringBuilder();
790
791 Xml.Append("<query xmlns='");
793 Xml.Append("'>");
794
795 await this.AppendItemInformation(Xml, e, Node);
796
797 Xml.Append("</query>");
798
799 await e.IqResult(Xml.ToString(), e.To);
800 }
801
808 protected virtual Task AppendServiceDiscoveryIdentities(StringBuilder Xml, IqEventArgs e, string Node)
809 {
810 return Task.CompletedTask;
811 }
812
819 protected virtual Task AppendServiceDiscoveryFeatures(StringBuilder Xml, IqEventArgs e, string Node)
820 {
821 return Task.CompletedTask;
822 }
823
830 protected virtual Task AppendItemInformation(StringBuilder Xml, IqEventArgs e, string Node)
831 {
832 return Task.CompletedTask;
833 }
834
835 #endregion
836
837 #region ISender
838
847 public virtual Task<string> IqError(string Id, XmppAddress To, XmppAddress From, Exception ex)
848 {
849 return Task.FromResult(string.Empty); // Do nothing by default.
850 }
851
860 public virtual Task<bool> IqError(string Id, XmppAddress To, XmppAddress From, string ErrorXml)
861 {
862 return Task.FromResult(true); // Do nothing by default.
863 }
864
873 public virtual Task<bool> IqResult(string Id, XmppAddress To, XmppAddress From, string ResultXml)
874 {
875 return Task.FromResult(true); // Do nothing by default.
876 }
877
886 public virtual Task<bool> PresenceError(string Id, XmppAddress To, XmppAddress From, Exception ex)
887 {
888 return Task.FromResult(true); // Do nothing by default.
889 }
890
899 public virtual Task<bool> PresenceError(string Id, XmppAddress To, XmppAddress From, string ErrorXml)
900 {
901 return Task.FromResult(true); // Do nothing by default.
902 }
903
913 public virtual Task<bool> Presence(string Type, string Id, XmppAddress To, XmppAddress From, string Language, string ContentXml)
914 {
915 return Task.FromResult(true); // Do nothing by default.
916 }
917
927 public virtual Task<bool> Message(string Type, string Id, XmppAddress To, XmppAddress From, string Language, string ContentXml)
928 {
929 return Task.FromResult(true); // Do nothing by default.
930 }
931
940 public virtual Task<bool> MessageError(string Id, XmppAddress To, XmppAddress From, Exception ex)
941 {
942 return Task.FromResult(true); // Do nothing by default.
943 }
944
945 #endregion
946
947 }
948}
Helps with common XML-related tasks.
Definition: XML.cs:21
static string Attribute(XmlElement E, string Name)
Gets the value of an XML attribute.
Definition: XML.cs:1062
static string Encode(string s)
Encodes a string for use in XML.
Definition: XML.cs:29
Base class for components.
Definition: Component.cs:17
bool UnregisterMessageHandler(string LocalName, string Namespace, EventHandlerAsync< MessageEventArgs > Handler, bool RemoveNamespaceAsFeature)
Unregisters a message handler.
Definition: Component.cs:298
virtual Task AppendServiceDiscoveryIdentities(StringBuilder Xml, IqEventArgs e, string Node)
Appends component identities, as defined in XEP-0030, to a discovery response.
Definition: Component.cs:808
void RegisterIqSetHandler(string LocalName, string Namespace, EventHandlerAsync< IqEventArgs > Handler, bool PublishNamespaceAsFeature)
Registers an IQ-Set handler.
Definition: Component.cs:162
CaseInsensitiveString Subdomain
Subdomain name.
Definition: Component.cs:77
Component(XmppServer Server, CaseInsensitiveString Subdomain, string Name)
Base class for components.
Definition: Component.cs:56
CaseInsensitiveString SubdomainSuffixed
Subdomain name, suffixed with a period (.).
Definition: Component.cs:82
virtual Task< bool > PresenceError(string Id, XmppAddress To, XmppAddress From, Exception ex)
Sends an Presence Error stanza.
Definition: Component.cs:886
virtual Task< bool > IqError(string Id, XmppAddress To, XmppAddress From, string ErrorXml)
Sends an IQ Error stanza.
Definition: Component.cs:860
bool UnregisterPresenceHandler(string LocalName, string Namespace, EventHandlerAsync< PresenceEventArgs > Handler, bool RemoveNamespaceAsFeature)
Unregisters a presence handler.
Definition: Component.cs:327
void RegisterIqGetHandler(string LocalName, string Namespace, EventHandlerAsync< IqEventArgs > Handler, bool PublishNamespaceAsFeature)
Registers an IQ-Get handler.
Definition: Component.cs:150
static string InnerXmlNoJabberNamespace(XmlElement Xml)
Removes the jabber namespace from the outer XML of an element.
Definition: Component.cs:678
Task< bool > IQ(string Type, string Id, XmppAddress To, XmppAddress From, string Language, string ContentXml, ISender Sender)
IQ stanza.
Definition: Component.cs:495
void RegisterPresenceHandler(string LocalName, string Namespace, EventHandlerAsync< PresenceEventArgs > Handler, bool PublishNamespaceAsFeature)
Registers a presence handler.
Definition: Component.cs:214
virtual async Task DiscoveryQueryGet(object Sender, IqEventArgs e)
Get handler for Service Discovery query (XEP-0030).
Definition: Component.cs:702
virtual Task< bool > PresenceError(string Id, XmppAddress To, XmppAddress From, string ErrorXml)
Sends an Presence Error stanza.
Definition: Component.cs:899
virtual Task MessageNoHandlerReceived(MessageEventArgs e)
Message without corresponding handler received.
Definition: Component.cs:559
virtual async Task DiscoveryQueryItemsGet(object Sender, IqEventArgs e)
Get handler for Service Discovery items query (XEP-0030).
Definition: Component.cs:772
virtual Task< bool > MessageError(string Id, XmppAddress To, XmppAddress From, Exception ex)
Sends a message error.
Definition: Component.cs:940
Task< bool > Presence(string Type, string Id, XmppAddress To, XmppAddress From, string Language, string ContentXml, ISender Sender)
Presence stanza.
Definition: Component.cs:668
XmppAddress MainDomain
Main/principal domain address
Definition: Component.cs:87
readonly object synchObject
Synchronization object for thread-safe access to internal structures.
Definition: Component.cs:26
virtual Task< bool > Presence(string Type, string Id, XmppAddress To, XmppAddress From, string Language, string ContentXml)
Presence stanza.
Definition: Component.cs:913
virtual Task AppendItemInformation(StringBuilder Xml, IqEventArgs e, string Node)
Appends item information to a service item description response.
Definition: Component.cs:830
virtual Task AppendServiceDiscoveryFeatures(StringBuilder Xml, IqEventArgs e, string Node)
Appends custom service descriptions.
Definition: Component.cs:819
bool IsComponentDomain(CaseInsensitiveString Domain, bool IncludeAlternativeDomains)
Checks if a domain is the component domain, or optionally, an alternative component domain.
Definition: Component.cs:124
virtual void Dispose()
IDisposable.Dispose
Definition: Component.cs:102
async Task< bool > Message(string Type, string Id, XmppAddress To, XmppAddress From, string Language, Stanza Stanza, ISender Sender)
Message stanza.
Definition: Component.cs:510
async Task< bool > IQ(string Type, string Id, XmppAddress To, XmppAddress From, string Language, Stanza Stanza, ISender Sender)
IQ stanza.
Definition: Component.cs:370
virtual bool SupportsAccounts
If the component supports accounts (true), or if the subdomain name is the only valid address.
Definition: Component.cs:116
virtual Task< bool > Message(string Type, string Id, XmppAddress To, XmppAddress From, string Language, string ContentXml)
Message stanza.
Definition: Component.cs:927
async Task< bool > Presence(string Type, string Id, XmppAddress To, XmppAddress From, string Language, Stanza Stanza, ISender Sender)
Presence stanza.
Definition: Component.cs:604
XmppServer Server
XMPP Server.
Definition: Component.cs:97
virtual Task PresenceNoHandlerReceived(PresenceEventArgs e)
Presence stanza without a corresponding handler received.
Definition: Component.cs:653
virtual Task< bool > IqResult(string Id, XmppAddress To, XmppAddress From, string ResultXml)
Sends an IQ Result stanza.
Definition: Component.cs:873
bool UnregisterIqGetHandler(string LocalName, string Namespace, EventHandlerAsync< IqEventArgs > Handler, bool RemoveNamespaceAsFeature)
Unregisters an IQ-Get handler.
Definition: Component.cs:250
virtual Task< bool > SupportsNode(string Node)
If the component supports a named node.
Definition: Component.cs:762
virtual Task< bool > SupportsAccount(string Account)
If the component supports a named account.
Definition: Component.cs:752
bool UnregisterIqSetHandler(string LocalName, string Namespace, EventHandlerAsync< IqEventArgs > Handler, bool RemoveNamespaceAsFeature)
Unregisters an IQ-Set handler.
Definition: Component.cs:263
void UnregisterFeature(string Namespace)
Unregisters a feature.
Definition: Component.cs:352
virtual Task< string > IqError(string Id, XmppAddress To, XmppAddress From, Exception ex)
Sends an IQ Error stanza.
Definition: Component.cs:847
Task< bool > Message(string Type, string Id, XmppAddress To, XmppAddress From, string Language, string ContentXml, ISender Sender)
Message stanza.
Definition: Component.cs:574
void RegisterMessageHandler(string LocalName, string Namespace, EventHandlerAsync< MessageEventArgs > Handler, bool PublishNamespaceAsFeature)
Registers a message handler.
Definition: Component.cs:191
SortedDictionary< string, bool > features
Features supported by component.
Definition: Component.cs:21
Component(XmppServer Server, string Subdomain, string Name)
Base class for components.
Definition: Component.cs:45
void RegisterFeature(string Namespace)
Registers a feature.
Definition: Component.cs:234
Event arguments for IQ queries.
Definition: IqEventArgs.cs:12
Task IqResult(string Xml, string From)
Returns a response to the current request.
Definition: IqEventArgs.cs:113
Task IqErrorItemNotFound(XmppAddress From, string ErrorText, string Language)
Returns a item-not-found error.
Definition: IqEventArgs.cs:206
XmlElement Query
Query element, if found, null otherwise.
Definition: IqEventArgs.cs:70
XmppAddress To
To address attribute
Definition: IqEventArgs.cs:88
Associates a specific IQ request with an IQ response.
Definition: IqResponse.cs:11
async Task< KeyValuePair< string, bool > > GetResponse()
Gets the response of the IQ request.
Definition: IqResponse.cs:57
Maintains a set of IQ responses, for a limited time.
Definition: IqResponses.cs:12
Presence information event arguments.
Contains information about a stanza.
Definition: Stanza.cs:9
XmlElement StanzaElement
Stanza element.
Definition: Stanza.cs:113
Contains information about one XMPP address.
Definition: XmppAddress.cs:9
bool HasAccount
If the address has an account part.
Definition: XmppAddress.cs:167
CaseInsensitiveString Address
XMPP Address
Definition: XmppAddress.cs:37
CaseInsensitiveString Account
Account
Definition: XmppAddress.cs:124
const string DiscoveryItemsNamespace
http://jabber.org/protocol/disco#items (XEP-0030)
Definition: XmppServer.cs:138
const string DiscoveryNamespace
http://jabber.org/protocol/disco#info (XEP-0030)
Definition: XmppServer.cs:133
const string StanzaNamespace
urn:ietf:params:xml:ns:xmpp-stanzas (RFC 6120)
Definition: XmppServer.cs:103
Represents a case-insensitive string.
Static class managing persistent counters.
static Task< long > IncrementCounter(CaseInsensitiveString Key)
Increments a counter.
Interface for components.
Definition: IComponent.cs:10
Interface for senders of stanzas.
Definition: ISender.cs:10
Task< string > IqError(string Id, XmppAddress To, XmppAddress From, Exception ex)
Sends an IQ Error stanza.
Task< bool > IqResult(string Id, XmppAddress To, XmppAddress From, string ResultXml)
Sends an IQ Result stanza.