private void SearchResponse(object Sender, ServiceItemsDiscoveryEventArgs e) { EventHandler Callback = (EventHandler)e.State; SearchState State = new SearchState(this, e.Items, Callback); State.DoQuery(); }
private string[] SearchJIDs() { this.ConnectClients(); List <string> SupportsSearch = new List <string>(); ServiceDiscoveryEventArgs e = this.client1.ServiceDiscovery(this.client1.Domain, 10000); if (e.Features.ContainsKey(XmppClient.NamespaceSearch)) { SupportsSearch.Add(this.client1.Domain); } ServiceItemsDiscoveryEventArgs e2 = this.client1.ServiceItemsDiscovery(this.client1.Domain, 10000); foreach (Item Item in e2.Items) { e = this.client1.ServiceDiscovery(Item.JID, 10000); if (e.Features.ContainsKey(XmppClient.NamespaceSearch)) { SupportsSearch.Add(Item.JID); } } return(SupportsSearch.ToArray()); }
private Task SearchResponse(object Sender, ServiceItemsDiscoveryEventArgs e) { EventHandler Callback = (EventHandler)e.State; SearchState State = new SearchState(this, e.Items, Callback); State.DoQuery(); return(Task.CompletedTask); }
private void Print(ServiceItemsDiscoveryEventArgs e) { Console.Out.WriteLine(); Console.Out.WriteLine("Items:"); foreach (Item Item in e.Items) { Console.Out.WriteLine(Item.ToString()); } }
public void ServiceDiscovery_Test_04_ServerItems() { this.ConnectClients(); try { ServiceItemsDiscoveryEventArgs e = this.client1.ServiceItemsDiscovery(this.client1.Domain, 10000); this.Print(e); } finally { this.DisposeClients(); } }
public void ServiceDiscovery_Test_06_AccountItems() { this.ConnectClients(); try { ServiceItemsDiscoveryEventArgs e = this.client1.ServiceItemsDiscovery(this.client2.BareJID, 10000); this.Print(e); } finally { this.DisposeClients(); } }
public void ServiceDiscovery_Test_05_ServerItemFeatures() { this.ConnectClients(); try { ServiceItemsDiscoveryEventArgs e = this.client1.ServiceItemsDiscovery(this.client1.Domain, 10000); foreach (Item Item in e.Items) { ServiceDiscoveryEventArgs e2 = this.client1.ServiceDiscovery(Item.JID, 10000); Console.Out.WriteLine(); Console.Out.WriteLine(Item.ToString()); Console.Out.WriteLine(new string('=', 80)); this.Print(e2); } } finally { this.DisposeClients(); } }
/// <summary> /// Loads simple XMPP configuration from an XML file. If file does not exist, or is not valid, a console dialog with the user is performed, /// to get the relevant information, test it, and create the corresponding XML file for later use. /// </summary> /// <param name="FileName">Name of configuration file.</param> /// <param name="DefaultAccountName">Default account name.</param> /// <param name="DefaultPassword">Default password.</param> /// <param name="AppAssembly">Application assembly.</param> /// <returns>Simple XMPP configuration.</returns> public static XmppCredentials GetConfigUsingSimpleConsoleDialog(string FileName, string DefaultAccountName, string DefaultPassword, Assembly AppAssembly) { try { return(Load(FileName)); } catch (Exception #if WINDOWS_UWP ex #endif ) { XmppCredentials Credentials = new XmppCredentials(); bool Ok; Credentials.Host = DefaultXmppServer; Credentials.Port = XmppCredentials.DefaultPort; Credentials.Account = DefaultAccountName; Credentials.Password = DefaultPassword; #if WINDOWS_UWP using (XmppClient Client = new XmppClient(Credentials, "en", AppAssembly)) { Client.Connect(); ManualResetEvent Connected = new ManualResetEvent(false); ManualResetEvent Failure = new ManualResetEvent(false); Client.OnStateChanged += (sender, NewState) => { switch (NewState) { case XmppState.Connected: Credentials.Password = Client.PasswordHash; Credentials.PasswordType = Client.PasswordHashMethod; Connected.Set(); break; case XmppState.Error: Failure.Set(); break; } }; switch (WaitHandle.WaitAny(new WaitHandle[] { Connected, Failure }, 20000)) { case 0: Ok = true; break; case 1: default: Ok = false; break; } if (Ok) { ServiceItemsDiscoveryEventArgs e = Client.ServiceItemsDiscovery(Client.Domain, 10000); foreach (Item Item in e.Items) { ServiceDiscoveryEventArgs e2 = Client.ServiceDiscovery(Item.JID, 10000); if (e2.Features.ContainsKey("urn:ieee:iot:disco:1.0") && string.IsNullOrEmpty(Credentials.ThingRegistry)) { Credentials.ThingRegistry = Item.JID; } else { Credentials.ThingRegistry = string.Empty; } if (e2.Features.ContainsKey("urn:ieee:iot:prov:d:1.0") && string.IsNullOrEmpty(Credentials.Provisioning)) { Credentials.Provisioning = Item.JID; } else { Credentials.Provisioning = string.Empty; } if (e2.Features.ContainsKey("urn:xmpp:eventlog") && string.IsNullOrEmpty(Credentials.Events)) { Credentials.Events = Item.JID; } else { Credentials.Events = string.Empty; } } } else { System.Runtime.ExceptionServices.ExceptionDispatchInfo.Capture(ex).Throw(); } } #else ConsoleColor FgBak = Console.ForegroundColor; string s; string Default; do { Console.ForegroundColor = ConsoleColor.Yellow; Console.Out.WriteLine(); Console.Out.WriteLine("To setup a connection to the XMPP network, please answer the following"); Console.Out.WriteLine("questions:"); Default = Credentials.Host; Console.Out.WriteLine(); Console.Out.WriteLine("What XMPP server do you want to use? Press ENTER to use " + Default); do { Console.ForegroundColor = ConsoleColor.White; Console.Out.Write("XMPP Server: "); Credentials.Host = Console.In.ReadLine(); if (string.IsNullOrEmpty(Credentials.Host)) { Credentials.Host = Default; } Console.ForegroundColor = ConsoleColor.Green; Console.Out.WriteLine(); Console.Out.WriteLine("You've selected to use '" + Credentials.Host + "'. Is this correct? [y/n]"); s = Console.In.ReadLine(); Console.Out.WriteLine(); }while (!s.StartsWith("y", StringComparison.InvariantCultureIgnoreCase)); Default = Credentials.Port.ToString(); Console.ForegroundColor = ConsoleColor.Yellow; Console.Out.WriteLine("What port do you want to connect to? Press ENTER to use " + Default); do { Console.ForegroundColor = ConsoleColor.White; int Port; do { Console.Out.Write("Port Number: "); s = Console.In.ReadLine(); if (string.IsNullOrEmpty(s)) { s = Default; } }while (!int.TryParse(s, out Port) || Port < 1 || Port > 65535); Credentials.Port = Port; Console.ForegroundColor = ConsoleColor.Green; Console.Out.WriteLine(); Console.Out.WriteLine("You've selected to use '" + Credentials.Port.ToString() + "'. Is this correct? [y/n]"); s = Console.In.ReadLine(); Console.Out.WriteLine(); }while (!s.StartsWith("y", StringComparison.InvariantCultureIgnoreCase)); Default = Credentials.Account; Console.ForegroundColor = ConsoleColor.Yellow; Console.Out.WriteLine("What account to you want to connect with? If the account does not exist,"); Console.Out.WriteLine("but the server supports In-band registration, the account will be created."); if (!string.IsNullOrEmpty(Default)) { Console.Out.WriteLine("Press ENTER to use " + Default); } do { Console.ForegroundColor = ConsoleColor.White; do { Console.Out.Write("Account: "); Credentials.Account = Console.In.ReadLine(); if (string.IsNullOrEmpty(Credentials.Account)) { Credentials.Account = Default; } }while (string.IsNullOrEmpty(Credentials.Account)); Console.ForegroundColor = ConsoleColor.Green; Console.Out.WriteLine(); Console.Out.WriteLine("You've selected to use '" + Credentials.Account + "'. Is this correct? [y/n]"); s = Console.In.ReadLine(); Console.Out.WriteLine(); }while (!s.StartsWith("y", StringComparison.InvariantCultureIgnoreCase)); Default = Credentials.Password; Console.ForegroundColor = ConsoleColor.Yellow; Console.Out.WriteLine("What password goes with the account? Remember that the configuration will,"); Console.Out.Write("be stored in a simple text file along with the application. "); if (!string.IsNullOrEmpty(Default)) { Console.Out.WriteLine("Press ENTER to use " + Default); } do { Console.ForegroundColor = ConsoleColor.White; do { Console.Out.Write("Password: "******"You've selected to use '" + Credentials.Password + "'. Is this correct? [y/n]"); s = Console.In.ReadLine(); Console.Out.WriteLine(); }while (!s.StartsWith("y", StringComparison.InvariantCultureIgnoreCase)); Console.ForegroundColor = ConsoleColor.Yellow; Console.Out.WriteLine("Do you want to trust the server? It's better not to trust the server."); Console.Out.WriteLine("This will force the server certificate to be validated, and the server"); Console.Out.WriteLine("trusted only if the certificate is valid. If there's a valid problem with"); Console.Out.WriteLine("the server certificate however, you might need to trust the server to"); Console.Out.WriteLine("be able to proceed."); do { Console.ForegroundColor = ConsoleColor.White; Console.Out.Write("Trust server [y/n]? "); s = Console.In.ReadLine(); Credentials.TrustServer = s.StartsWith("y", StringComparison.InvariantCultureIgnoreCase); }while (!Credentials.TrustServer && !s.StartsWith("n", StringComparison.InvariantCultureIgnoreCase)); Console.ForegroundColor = ConsoleColor.Yellow; Console.Out.WriteLine("Do you want to create an account on the server?"); do { Console.ForegroundColor = ConsoleColor.White; Console.Out.Write("Create account [y/n]? "); s = Console.In.ReadLine(); Credentials.AllowRegistration = s.StartsWith("y", StringComparison.InvariantCultureIgnoreCase); }while (!Credentials.AllowRegistration && !s.StartsWith("n", StringComparison.InvariantCultureIgnoreCase)); if (Credentials.AllowRegistration) { Console.ForegroundColor = ConsoleColor.Yellow; Console.Out.WriteLine(); Console.Out.WriteLine("Some servers require an API key to allow account creation."); Console.Out.WriteLine("If so, please enter an API key below."); Default = Credentials.FormSignatureKey; Console.Out.WriteLine(); Console.Out.WriteLine("What API Key do you want to use? Press ENTER to use " + Default); do { Console.ForegroundColor = ConsoleColor.White; Console.Out.Write("API Key: "); Credentials.FormSignatureKey = Console.In.ReadLine(); if (string.IsNullOrEmpty(Credentials.FormSignatureKey)) { Credentials.FormSignatureKey = Default; } Console.ForegroundColor = ConsoleColor.Green; Console.Out.WriteLine(); Console.Out.WriteLine("You've selected to use '" + Credentials.FormSignatureKey + "'. Is this correct? [y/n]"); s = Console.In.ReadLine(); Console.Out.WriteLine(); }while (!s.StartsWith("y", StringComparison.InvariantCultureIgnoreCase)); if (!string.IsNullOrEmpty(Credentials.FormSignatureKey)) { Console.ForegroundColor = ConsoleColor.Yellow; Console.Out.WriteLine(); Console.Out.WriteLine("Please provide the corresponding secret below."); Default = Credentials.FormSignatureSecret; Console.Out.WriteLine(); Console.Out.WriteLine("What secret belongs to the API key? Press ENTER to use " + Default); do { Console.ForegroundColor = ConsoleColor.White; Console.Out.Write("Secret: "); Credentials.FormSignatureSecret = Console.In.ReadLine(); if (string.IsNullOrEmpty(Credentials.FormSignatureSecret)) { Credentials.FormSignatureSecret = Default; } Console.ForegroundColor = ConsoleColor.Green; Console.Out.WriteLine(); Console.Out.WriteLine("You've selected to use '" + Credentials.FormSignatureSecret + "'. Is this correct? [y/n]"); s = Console.In.ReadLine(); Console.Out.WriteLine(); }while (!s.StartsWith("y", StringComparison.InvariantCultureIgnoreCase)); } } Console.ForegroundColor = ConsoleColor.Yellow; Console.Out.WriteLine("I will now try to connect to the server to see if the information"); Console.Out.WriteLine("provided is correct."); using (XmppClient Client = new XmppClient(Credentials, "en", AppAssembly)) { Client.Connect(); ManualResetEvent Connected = new ManualResetEvent(false); ManualResetEvent Failure = new ManualResetEvent(false); Client.OnStateChanged += (sender, NewState) => { Console.Out.WriteLine(NewState.ToString()); switch (NewState) { case XmppState.Connected: Console.ForegroundColor = ConsoleColor.Green; Console.Out.WriteLine("Connection successful."); Credentials.Password = Client.PasswordHash; Credentials.PasswordType = Client.PasswordHashMethod; Credentials.AllowRegistration = false; Credentials.FormSignatureKey = string.Empty; Credentials.FormSignatureSecret = string.Empty; Connected.Set(); break; case XmppState.Error: Console.ForegroundColor = ConsoleColor.Red; Console.Out.WriteLine("Connection failed. Please update connection information."); Failure.Set(); break; } }; switch (WaitHandle.WaitAny(new WaitHandle[] { Connected, Failure }, 20000)) { case 0: Ok = true; break; case 1: default: Ok = false; break; } if (Ok) { Console.ForegroundColor = ConsoleColor.Yellow; Console.Out.WriteLine("Checking server capabilities."); ServiceItemsDiscoveryEventArgs e = Client.ServiceItemsDiscovery(Client.Domain, 10000); foreach (Item Item in e.Items) { Console.Out.WriteLine("Checking " + Item.JID + "."); ServiceDiscoveryEventArgs e2 = Client.ServiceDiscovery(Item.JID, 10000); if (e2.Features.ContainsKey("urn:ieee:iot:disco:1.0") && string.IsNullOrEmpty(Credentials.ThingRegistry)) { Console.Out.WriteLine("Thing registry found."); Credentials.ThingRegistry = Item.JID; } else { Credentials.ThingRegistry = string.Empty; } if (e2.Features.ContainsKey("urn:ieee:iot:prov:d:1.0") && string.IsNullOrEmpty(Credentials.Provisioning)) { Console.Out.WriteLine("Provisioning server found."); Credentials.Provisioning = Item.JID; } else { Credentials.Provisioning = string.Empty; } if (e2.Features.ContainsKey("urn:xmpp:eventlog") && string.IsNullOrEmpty(Credentials.Events)) { Console.Out.WriteLine("Event log found."); Credentials.Events = Item.JID; } else { Credentials.Events = string.Empty; } } } } }while (!Ok); Default = Credentials.ThingRegistry; Console.ForegroundColor = ConsoleColor.Yellow; Console.Out.WriteLine("What thing registry do you want to use? The use of a thing registry is optional."); if (string.IsNullOrEmpty(Default)) { Console.Out.WriteLine("Press ENTER to not use a thing registry."); } else { Console.Out.WriteLine("Press ENTER to use " + Default); } do { Console.ForegroundColor = ConsoleColor.White; Console.Out.Write("Thing Registry: "); Credentials.ThingRegistry = Console.In.ReadLine(); if (string.IsNullOrEmpty(Credentials.ThingRegistry)) { Credentials.ThingRegistry = Default; } Console.ForegroundColor = ConsoleColor.Green; Console.Out.WriteLine(); if (string.IsNullOrEmpty(Credentials.ThingRegistry)) { Console.Out.WriteLine("You've selected to not use a thing registry. Is this correct? [y/n]"); } else { Console.Out.WriteLine("You've selected to use '" + Credentials.ThingRegistry + "'. Is this correct? [y/n]"); } s = Console.In.ReadLine(); Console.Out.WriteLine(); }while (!s.StartsWith("y", StringComparison.InvariantCultureIgnoreCase)); Default = Credentials.Provisioning; Console.ForegroundColor = ConsoleColor.Yellow; Console.Out.WriteLine("What provisioning server do you want to use? The use of a provisioning server"); Console.Out.WriteLine("is optional."); if (string.IsNullOrEmpty(Default)) { Console.Out.WriteLine("Press ENTER to not use a provisioning server."); } else { Console.Out.WriteLine("Press ENTER to use " + Default); } do { Console.ForegroundColor = ConsoleColor.White; Console.Out.Write("Provisioning Server: "); Credentials.Provisioning = Console.In.ReadLine(); if (string.IsNullOrEmpty(Credentials.Provisioning)) { Credentials.Provisioning = Default; } Console.ForegroundColor = ConsoleColor.Green; Console.Out.WriteLine(); if (string.IsNullOrEmpty(Credentials.Provisioning)) { Console.Out.WriteLine("You've selected to not use a provisioning server. Is this correct? [y/n]"); } else { Console.Out.WriteLine("You've selected to use '" + Credentials.Provisioning + "'. Is this correct? [y/n]"); } s = Console.In.ReadLine(); Console.Out.WriteLine(); }while (!s.StartsWith("y", StringComparison.InvariantCultureIgnoreCase)); Default = Credentials.Events; Console.ForegroundColor = ConsoleColor.Yellow; Console.Out.WriteLine("What event log do you want to use? The use of a event logs is optional."); if (string.IsNullOrEmpty(Default)) { Console.Out.WriteLine("Press ENTER to not use an event log."); } else { Console.Out.WriteLine("Press ENTER to use " + Default); } do { Console.ForegroundColor = ConsoleColor.White; Console.Out.Write("Event Log: "); Credentials.Events = Console.In.ReadLine(); if (string.IsNullOrEmpty(Credentials.Events)) { Credentials.Events = Default; } Console.ForegroundColor = ConsoleColor.Green; Console.Out.WriteLine(); if (string.IsNullOrEmpty(Credentials.Events)) { Console.Out.WriteLine("You've selected to not use an event log. Is this correct? [y/n]"); } else { Console.Out.WriteLine("You've selected to use '" + Credentials.Events + "'. Is this correct? [y/n]"); } s = Console.In.ReadLine(); Console.Out.WriteLine(); }while (!s.StartsWith("y", StringComparison.InvariantCultureIgnoreCase)); Console.ForegroundColor = ConsoleColor.Yellow; Console.Out.WriteLine("Do you want to use a sniffer? If you use a sniffer, XMPP network"); Console.Out.WriteLine("communication will be Output to the console in real-time. This can"); Console.Out.WriteLine("come in handy when debugging network communication."); do { Console.ForegroundColor = ConsoleColor.White; Console.Out.Write("Sniffer [y/n]? "); s = Console.In.ReadLine(); Credentials.Sniffer = s.StartsWith("y", StringComparison.InvariantCultureIgnoreCase); }while (!Credentials.Sniffer && !s.StartsWith("n", StringComparison.InvariantCultureIgnoreCase)); Console.Out.WriteLine(); Console.ForegroundColor = FgBak; #endif SaveSimpleXmppConfiguration(FileName, Credentials); return(Credentials); } }
private async void Client_OnStateChanged(object Sender, XmppState NewState) { if (!(Sender is XmppClient Client)) { return; } if (!Client.TryGetTag("TabID", out object Obj) || !(Obj is string TabID)) { return; } try { string Msg; switch (NewState) { case XmppState.Authenticating: Client.SetTag("StartedAuthentication", true); Client.SetTag("EncyptionSuccessful", true); if (this.Step == 0) { ClientEvents.PushEvent(new string[] { TabID }, "ConnectionOK0", "Connection established.", false, "User"); this.client.Dispose(); this.client = null; this.Step = 1; this.Updated = DateTime.Now; await Database.Update(this); return; } else { Msg = "Authenticating user."; } break; case XmppState.Binding: Msg = "Binding to resource."; break; case XmppState.Connected: this.bareJid = Client.BareJID; if (this.createAccount && !string.IsNullOrEmpty(this.accountHumanReadableName)) { ClientEvents.PushEvent(new string[] { TabID }, "ShowStatus", "Setting vCard.", false, "User"); StringBuilder Xml = new StringBuilder(); Xml.Append("<vCard xmlns='vcard-temp'>"); Xml.Append("<FN>"); Xml.Append(XML.Encode(this.accountHumanReadableName)); Xml.Append("</FN>"); Xml.Append("<JABBERID>"); Xml.Append(XML.Encode(this.client.BareJID)); Xml.Append("</JABBERID>"); Xml.Append("</vCard>"); await Client.IqSetAsync(this.client.BareJID, Xml.ToString()); } ClientEvents.PushEvent(new string[] { TabID }, "ShowStatus", "Checking server features.", false, "User"); ServiceDiscoveryEventArgs e = await Client.ServiceDiscoveryAsync(null, string.Empty, string.Empty); if (e.Ok) { this.offlineMessages = e.HasFeature("msgoffline"); this.blocking = e.HasFeature(Networking.XMPP.Abuse.AbuseClient.NamespaceBlocking); this.reporting = e.HasFeature(Networking.XMPP.Abuse.AbuseClient.NamespaceReporting); this.abuse = e.HasFeature(Networking.XMPP.Abuse.AbuseClient.NamespaceAbuseReason); this.spam = e.HasFeature(Networking.XMPP.Abuse.AbuseClient.NamespaceSpamReason); this.mail = e.HasFeature("urn:xmpp:smtp"); } else { this.offlineMessages = false; this.blocking = false; this.reporting = false; this.abuse = false; this.spam = false; this.mail = false; } ClientEvents.PushEvent(new string[] { TabID }, "ShowStatus", "Checking account features.", false, "User"); e = await Client.ServiceDiscoveryAsync(null, Client.BareJID, string.Empty); this.pep = e.Ok && this.ContainsIdentity("pep", "pubsub", e); ClientEvents.PushEvent(new string[] { TabID }, "ShowStatus", "Checking server components.", false, "User"); ServiceItemsDiscoveryEventArgs e2 = await Client.ServiceItemsDiscoveryAsync(null, string.Empty, string.Empty); this.thingRegistry = string.Empty; this.provisioning = string.Empty; this.events = string.Empty; this.pubSub = string.Empty; this.legal = string.Empty; this.software = string.Empty; if (e2.Ok) { foreach (Item Item in e2.Items) { ClientEvents.PushEvent(new string[] { TabID }, "ShowStatus", "Checking component features for " + Item.JID, false, "User"); e = await Client.ServiceDiscoveryAsync(null, Item.JID, string.Empty); if (e.HasFeature(Networking.XMPP.Provisioning.ThingRegistryClient.NamespaceDiscovery)) { this.thingRegistry = Item.JID; } if (e.HasFeature(Networking.XMPP.Provisioning.ProvisioningClient.NamespaceProvisioningDevice)) { this.provisioning = Item.JID; } if (e.HasFeature(Networking.XMPP.PubSub.PubSubClient.NamespacePubSub) && this.ContainsIdentity("service", "pubsub", e)) { this.pubSub = Item.JID; } if (e.HasFeature(Waher.Events.XMPP.XmppEventSink.NamespaceEventLogging)) { this.events = Item.JID; } if (e.HasFeature(Networking.XMPP.Contracts.ContractsClient.NamespaceLegalIdentities)) { this.legal = Item.JID; } if (e.HasFeature(Networking.XMPP.Software.SoftwareUpdateClient.NamespaceSoftwareUpdates)) { this.software = Item.JID; } } } Dictionary <string, object> ConnectionInfo = new Dictionary <string, object>() { { "msg", "Connection successful." }, { "offlineMsg", this.offlineMessages }, { "blocking", this.blocking }, { "reporting", this.reporting }, { "abuse", this.abuse }, { "spam", this.spam }, { "mail", this.mail }, { "pep", this.pep ? this.bareJid : string.Empty }, { "thingRegistry", this.thingRegistry }, { "provisioning", this.provisioning }, { "eventLog", this.events }, { "pubSub", this.pubSub }, { "legal", this.legal }, { "software", this.software } }; ClientEvents.PushEvent(new string[] { TabID }, "ConnectionOK1", JSON.Encode(ConnectionInfo, false), true, "User"); this.client.Dispose(); this.client = null; this.Step = 2; this.Updated = DateTime.Now; await Database.Update(this); return; case XmppState.Connecting: Msg = "Connecting to server."; break; case XmppState.Error: bool Error = false; Msg = string.Empty; if (this.Step == 0 && this.transportMethod == XmppTransportMethod.C2S) { this.customBinding = true; ClientEvents.PushEvent(new string[] { TabID }, "ShowStatus", "Unable to connect properly. Looking for alternative ways to connect.", false, "User"); ClientEvents.PushEvent(new string[] { TabID }, "ShowCustomProperties", "{\"visible\":true}", true, "User"); using (HttpClient HttpClient = new HttpClient(new HttpClientHandler() { #if !NETFW ServerCertificateCustomValidationCallback = this.RemoteCertificateValidationCallback, #endif UseCookies = false }) { Timeout = TimeSpan.FromMilliseconds(60000) }) { try { HttpResponseMessage Response = await HttpClient.GetAsync("http://" + this.host + "/.well-known/host-meta"); Response.EnsureSuccessStatusCode(); Stream Stream = await Response.Content.ReadAsStreamAsync(); // Regardless of status code, we check for XML content. byte[] Bin = await Response.Content.ReadAsByteArrayAsync(); string CharSet = Response.Content.Headers.ContentType.CharSet; Encoding Encoding; if (string.IsNullOrEmpty(CharSet)) { Encoding = Encoding.UTF8; } else { Encoding = InternetContent.GetEncoding(CharSet); } string XmlResponse = Encoding.GetString(Bin); XmlDocument Doc = new XmlDocument(); Doc.LoadXml(XmlResponse); if (Doc.DocumentElement != null && Doc.DocumentElement.LocalName == "XRD") { string BoshUrl = null; string WsUrl = null; foreach (XmlNode N in Doc.DocumentElement.ChildNodes) { if (N is XmlElement E && E.LocalName == "Link") { switch (XML.Attribute(E, "rel")) { case "urn:xmpp:alt-connections:xbosh": BoshUrl = XML.Attribute(E, "href"); break; case "urn:xmpp:alt-connections:websocket": WsUrl = XML.Attribute(E, "href"); break; } } } if (!string.IsNullOrEmpty(WsUrl)) { this.wsUrl = WsUrl; this.transportMethod = XmppTransportMethod.WS; ClientEvents.PushEvent(new string[] { TabID }, "ShowTransport", "{\"method\":\"WS\"}", true, "User"); this.Connect(TabID); return; } else if (!string.IsNullOrEmpty(BoshUrl)) { this.boshUrl = BoshUrl; this.transportMethod = XmppTransportMethod.BOSH; ClientEvents.PushEvent(new string[] { TabID }, "ShowTransport", "{\"method\":\"BOSH\"}", true, "User"); this.Connect(TabID); return; } } } catch (Exception) { // Ignore. } Msg = "No alternative binding methods found."; Error = true; } } else { Msg = "Unable to connect properly."; Error = true; if (Client.TryGetTag("StartedAuthentication", out Obj) && Obj is bool b && b) { if (this.createAccount) { ClientEvents.PushEvent(new string[] { TabID }, "ShowFail2", Msg, false, "User"); } else { ClientEvents.PushEvent(new string[] { TabID }, "ShowFail1", Msg, false, "User"); } return; } } if (Error) { ClientEvents.PushEvent(new string[] { TabID }, "ConnectionError", Msg, false, "User"); this.client.Dispose(); this.client = null; return; } break; case XmppState.FetchingRoster: Msg = "Fetching roster from server."; break; case XmppState.Offline: Msg = "Offline."; break; case XmppState.Registering: Msg = "Registering account."; break; case XmppState.RequestingSession: Msg = "Requesting session."; break; case XmppState.SettingPresence: Msg = "Setting presence."; break; case XmppState.StartingEncryption: Msg = "Starting encryption."; Client.SetTag("StartedEncryption", true); break; case XmppState.StreamNegotiation: Msg = "Negotiating stream."; break; case XmppState.StreamOpened: Msg = "Stream opened."; break; default: Msg = NewState.ToString(); break; } ClientEvents.PushEvent(new string[] { TabID }, "ShowStatus", Msg, false, "User"); } catch (Exception ex) { Log.Critical(ex); ClientEvents.PushEvent(new string[] { TabID }, "ShowStatus", ex.Message, false, "User"); } }