Exemple #1
0
        /// <summary>
        /// Initiates the stream.
        /// </summary>
        private void OpenStream()
        {
            // Generate new client and message ids
            _clientId  = Guid.NewGuid().ToString();
            _messageId = 1;

            // Stream initialization request
            var xml = Xml.Element("stream:stream", "jabber:client")
                      .Attr("to", "connect.logitech.com")
                      .Attr("version", "1.0")
                      .Attr("xmlns:stream", "http://etherx.jabber.org/streams")
                      .Attr("xml:lang", CultureInfo.CurrentCulture.Name);

            Send(xml.ToXmlString(xmlDeclaration: true, leaveOpen: true));

            // Create a new parser instance.
            if (_parser != null)
            {
                _parser.Dispose();
            }

            _parser = new StreamParser(_stream, true);

            // The first element of the stream must be <stream:features>.
            var features = _parser.NextElement("stream:features");

            MessageReceived?.Invoke(this, new MessageReceivedEventArgs(features.OuterXml));

            // Enable keepalive
            if (_heartbeat != null)
            {
                _heartbeat.Dispose();
            }

            _heartbeat          = new System.Timers.Timer();
            _heartbeat.Elapsed += HeatbeatAsync;
            _heartbeat.Interval = 30000;
            _heartbeat.Start();

            Connected = true;
        }
Exemple #2
0
        /// <summary>
        /// Gets the session token for the supplied Logitech username and password.
        /// </summary>
        /// <param name="ip">IP address of the Harmony Hub.</param>
        /// <param name="username">Username.</param>
        /// <param name="password">Passwprd.</param>
        /// <returns>Harmony session token.</returns>
        private string GetSessionToken(string ip, string username, string password, bool bypassLogitech)
        {
            var sessionToken = "";

            var authToken = "";;

            if (!bypassLogitech)
            {
                // Authenticate to Logitech
                authToken = LoginToLogitech(username, password);
                if (string.IsNullOrEmpty(authToken))
                {
                    throw new AuthTokenException("Could not get token from Logitech server.");
                }
            }

            // Swap auth token for a session token
            using (var authClient = new TcpClient(ip, 5222))
            {
                using (var authStream = authClient.GetStream())
                {
                    // Initialize stream
                    var streamXml = Xml.Element("stream:stream", "jabber:client")
                                    .Attr("to", "connect.logitech.com")
                                    .Attr("version", "1.0")
                                    .Attr("xmlns:stream", "http://etherx.jabber.org/streams")
                                    .Attr("xml:lang", CultureInfo.CurrentCulture.Name);
                    byte[] streamBuffer = Encoding.UTF8.GetBytes(streamXml.ToXmlString(xmlDeclaration: true, leaveOpen: true));
                    authStream.Write(streamBuffer, 0, streamBuffer.Length);

                    // Begin reading auth stream
                    using (var authParser = new StreamParser(authStream, true))
                    {
                        // The first element of the stream must be <stream:features>.
                        var features = authParser.NextElement("stream:features");
                        MessageReceived?.Invoke(this, new MessageReceivedEventArgs(features.OuterXml));

                        // Auth as guest
                        // <auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='PLAIN'>AGd1ZXN0QHguY29tAGd1ZXN0</auth>
                        var saslXml = Xml.Element("auth", "urn:ietf:params:xml:ns:xmpp-sasl")
                                      .Attr("mechanism", "PLAIN")
                                      .Text(Convert.ToBase64String(Encoding.UTF8.GetBytes("\0" + "*****@*****.**" + "\0" + "guest")));
                        byte[] saslBuffer = Encoding.UTF8.GetBytes(saslXml.ToXmlString());
                        authStream.Write(saslBuffer, 0, saslBuffer.Length);

                        // Handle response
                        while (true)
                        {
                            var response = authParser.NextElement("challenge", "success", "failure");
                            MessageReceived?.Invoke(this, new MessageReceivedEventArgs(response.OuterXml));
                            if (response.Name != "success")
                            {
                                throw new SaslAuthenticationException("SASL authentication failed.");
                            }

                            break;
                        }

                        // Swap the authToken for a sessionToken on the Harmony Hub

                        /*
                         * <iq type="get" id="3174962747" from="guest">
                         *   <oa xmlns="connect.logitech.com" mime="vnd.logitech.connect/vnd.logitech.pair">
                         *     token=y6jZtSuYYOoQ2XXiU9cYovqtT+cCbcyjhWqGbhQsLV/mWi4dJVglFEBGpm08OjCW:name=SOMEID#iOS6.0.1#iPhone
                         *   </oa>
                         * </iq>
                         */
                        var methodOrToken = bypassLogitech ? "method=pair" : "token=" + authToken;
                        var swapXml       = Xml.Element("iq")
                                            .Attr("type", "get")
                                            .Attr("id", _clientId + "_" + _messageId.ToString())
                                            .Child(Xml.Element("oa", "connect.logitech.com")
                                                   .Attr("mime", HarmonyMimeTypes.Pair)
                                                   .Text(methodOrToken + ":name=foo#iOS8.3.0#iPhone"));
                        byte[] swapBuffer = Encoding.UTF8.GetBytes(swapXml.ToXmlString());
                        authStream.Write(swapBuffer, 0, swapBuffer.Length);

                        // Handle response
                        while (true)
                        {
                            XmlElement ret = authParser.NextElement("iq");
                            MessageReceived?.Invoke(this, new MessageReceivedEventArgs(ret.OuterXml));
                            if (ret.Name == "iq")
                            {
                                if (ret.FirstChild != null && ret.FirstChild.Name == "oa")
                                {
                                    if (ret.FirstChild.InnerXml.Contains("status=succeeded"))
                                    {
                                        const string identityRegEx = "identity=([A-Z0-9]{8}-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{12}):status";
                                        var          regex         = new Regex(identityRegEx, RegexOptions.IgnoreCase | RegexOptions.Singleline);
                                        var          match         = regex.Match(ret.FirstChild.InnerXml);
                                        if (match.Success)
                                        {
                                            sessionToken = match.Groups[1].ToString();
                                            break;
                                        }
                                        else
                                        {
                                            throw new AuthTokenException("AuthToken swap failed.");
                                        }
                                    }
                                }
                            }
                        }
                    }

                    // Kill stream
                    byte[] killBuffer = Encoding.UTF8.GetBytes("</stream:stream>");
                    authStream.Write(killBuffer, 0, killBuffer.Length);
                }
            }

            return(sessionToken);
        }