Example #1
0
        private async Task TestConnectionStateChanged(object Sender, XmppState State)
        {
            Log.Informational("Changing state: " + State.ToString());

            switch (State)
            {
            case XmppState.Connected:
                await RuntimeSettings.SetAsync("XmppHost", this.xmppClient.Host);

                await RuntimeSettings.SetAsync("XmppPort", this.xmppClient.Port);

                await RuntimeSettings.SetAsync("XmppUserName", this.xmppClient.UserName);

                await RuntimeSettings.SetAsync("XmppPasswordHash", this.xmppClient.PasswordHash);

                await RuntimeSettings.SetAsync("XmppPasswordHashMethod", this.xmppClient.PasswordHashMethod);

                this.xmppClient.OnStateChanged -= this.TestConnectionStateChanged;
                this.xmppClient.OnStateChanged += this.StateChanged;
                await this.SetVCard();

                await this.RegisterDevice();

                break;

            case XmppState.Error:
            case XmppState.Offline:
                if (!(this.xmppClient is null))
                {
                    await MainPage.Instance.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
                                                                async() => await this.ShowConnectionDialog(this.xmppClient.Host, this.xmppClient.Port, this.xmppClient.UserName));
                }
                break;
            }
        }
Example #2
0
        private void StateChanged(object Sender, XmppState State)
        {
            Log.Informational("Changing state: " + State.ToString());

            if (State == XmppState.Connected)
            {
                Log.Informational("Connected as " + this.xmppClient.FullJID);
                Task.Run(this.SetVCard);
                Task.Run(this.RegisterDevice);
            }
        }
Example #3
0
        private Task StateChanged(object _, XmppState State)
        {
            Log.Informational("Changing state: " + State.ToString());

            if (State == XmppState.Connected)
            {
                Log.Informational("Connected as " + this.xmppClient.FullJID);
                Task.Run(this.SetVCard);
                Task.Run(this.RegisterDevice);
            }

            return(Task.CompletedTask);
        }
        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");
            }
        }
        private async Task XmppClient_StateChanged(object sender, XmppState newState)
        {
            this.xmppThread?.NewState(newState.ToString());

            switch (newState)
            {
            case XmppState.Connected:
                this.LatestError           = string.Empty;
                this.LatestConnectionError = string.Empty;

                this.xmppSettingsOk = true;

                this.RecreateReconnectTimer();

                string legalJidBefore = this.tagProfile.LegalJid;
                if (this.tagProfile.NeedsUpdating())
                {
                    await this.DiscoverServices();
                }
                string legalJidAfter = this.tagProfile.LegalJid;

                bool legalJidWasCleared           = !string.IsNullOrWhiteSpace(legalJidBefore) && string.IsNullOrWhiteSpace(legalJidAfter);
                bool legalJidIsValid              = !string.IsNullOrWhiteSpace(legalJidAfter);
                bool legalJidHasChangedAndIsValid = legalJidIsValid && !string.Equals(legalJidBefore, legalJidAfter);

                // If LegalJid was cleared, or is different
                if (legalJidWasCleared || legalJidHasChangedAndIsValid)
                {
                    this.contracts.DestroyClients();
                }

                // If we have a valid Jid, and contracts isn't created yet.
                if (legalJidHasChangedAndIsValid || (legalJidIsValid && !this.contracts.IsOnline))
                {
                    try
                    {
                        await this.contracts.CreateClients(false);
                    }
                    catch (Exception e)
                    {
                        this.logService.LogException(e);
                    }
                }

                this.logService.AddListener(this.xmppEventSink);

                this.xmppThread?.Stop();
                this.xmppThread      = null;
                this.startupProfiler = null;
                break;

            case XmppState.Error:
                if (this.xmppSettingsOk)
                {
                    this.xmppSettingsOk = false;
                    this.xmppClient?.Reconnect();
                }

                this.xmppThread?.Stop();
                this.xmppThread      = null;
                this.startupProfiler = null;
                break;
            }

            this.OnConnectionStateChanged(new ConnectionStateChangedEventArgs(newState, this.userInitiatedLogInOrOut));
        }