src/HarmonyHub/Client.cs
/// <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>
/// <param name="bypassLogitech">if <c>false</c> use Logitech auth, otherwise bypass Logitech auth.</param>
/// <returns>Harmony session token.</returns>
Gets the session token for the supplied Logitech username and password.
Gets the session token for the supplied Logitech username and password .
private string GetSessionToken(string ip, string username, string password, bool bypassLogitech)
        {
            var sessionToken = string.Empty;
            var authToken = string.Empty;
            if (!bypassLogitech)
            {
                authToken = LoginToLogitech(username, password);
                if (string.IsNullOrEmpty(authToken))
                    throw new AuthTokenException("Could not get token from Logitech server.");
            }
            using (var authClient = new TcpClient(ip, 5222))
            {
                using (var authStream = authClient.GetStream())
                {
                    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);
                    using (var authParser = new StreamParser(authStream, true))
                    {
                        var features = authParser.NextElement("stream:features");
                        MessageReceived?.Invoke(this, new MessageReceivedEventArgs(features.OuterXml));
                        var saslXml = Xml.Element("auth", "urn:ietf:params:xml:ns:xmpp-sasl")
                            .Attr("mechanism", "PLAIN")
                            .Text(Convert.ToBase64String(Encoding.UTF8.GetBytes("\0" + "guest@x.com" + "\0" + "guest")));
                        byte[] saslBuffer = Encoding.UTF8.GetBytes(saslXml.ToXmlString());
                        authStream.Write(saslBuffer, 0, saslBuffer.Length);
                        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;
                        }
                        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);
                        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-fA-F0-9]+):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.");
                                        }
                                    }
                                }
                            }
                        }
                    }
                    byte[] killBuffer = Encoding.UTF8.GetBytes("</stream:stream>");
                    authStream.Write(killBuffer, 0, killBuffer.Length);
                }
            }
            return sessionToken;
        }
private string GetSessionToken ( string ip , string username , string password , bool bypassLogitech ) { var sessionToken = string . Empty ; var authToken = string . Empty ; if ( ! bypassLogitech ) { authToken = LoginToLogitech ( username , password ) ; if ( string . IsNullOrEmpty ( authToken ) ) throw new AuthTokenException ( " " ) ; } using ( var authClient = new TcpClient ( ip , 5222 ) ) { using ( var authStream = authClient . GetStream ( ) ) { var streamXml = Xml . Element ( " " , " " ) . Attr ( " " , " " ) . Attr ( " " , " " ) . Attr ( " " , " " ) . Attr ( " " , CultureInfo . CurrentCulture . Name ) ; byte [ ] streamBuffer = Encoding . UTF8 . GetBytes ( streamXml . ToXmlString ( xmlDeclaration : true , leaveOpen : true ) ) ; authStream . Write ( streamBuffer , 0 , streamBuffer . Length ) ; using ( var authParser = new StreamParser ( authStream , true ) ) { var features = authParser . NextElement ( " " ) ; MessageReceived ? . Invoke ( this , new MessageReceivedEventArgs ( features . OuterXml ) ) ; var saslXml = Xml . Element ( " " , " " ) . Attr ( " " , " " ) . Text ( Convert . ToBase64String ( Encoding . UTF8 . GetBytes ( " \0 " + " " + " \0 " + " " ) ) ) ; byte [ ] saslBuffer = Encoding . UTF8 . GetBytes ( saslXml . ToXmlString ( ) ) ; authStream . Write ( saslBuffer , 0 , saslBuffer . Length ) ; while ( true ) { var response = authParser . NextElement ( " " , " " , " " ) ; MessageReceived ? . Invoke ( this , new MessageReceivedEventArgs ( response . OuterXml ) ) ; if ( response . Name != " " ) throw new SaslAuthenticationException ( " " ) ; break ; } var methodOrToken = bypassLogitech ? " " : " " + authToken ; var swapXml = Xml . Element ( " " ) . Attr ( " " , " " ) . Attr ( " " , _clientId + " " + _messageId . ToString ( ) ) . Child ( Xml . Element ( " " , " " ) . Attr ( " " , HarmonyMimeTypes . Pair ) . Text ( methodOrToken + " " ) ) ; byte [ ] swapBuffer = Encoding . UTF8 . GetBytes ( swapXml . ToXmlString ( ) ) ; authStream . Write ( swapBuffer , 0 , swapBuffer . Length ) ; while ( true ) { XmlElement ret = authParser . NextElement ( " " ) ; MessageReceived ? . Invoke ( this , new MessageReceivedEventArgs ( ret . OuterXml ) ) ; if ( ret . Name == " " ) { if ( ret . FirstChild != null && ret . FirstChild . Name == " " ) { if ( ret . FirstChild . InnerXml . Contains ( " " ) ) { const string identityRegEx = " " ; 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 ( " " ) ; } } } } } } byte [ ] killBuffer = Encoding . UTF8 . GetBytes ( " " ) ; authStream . Write ( killBuffer , 0 , killBuffer . Length ) ; } } return sessionToken ; }
Gets the session token for the supplied Logitech username and password.
Gets the session token for the supplied Logitech username and password .
// Authenticate to Logitech // Swap auth token for a session token // Initialize stream // Begin reading auth stream // The first element of the stream must be <stream:features>. // Auth as guest // <auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='PLAIN'>AGd1ZXN0QHguY29tAGd1ZXN0</auth> // Handle response // 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>
                         */ // Handle response // Kill stream
Harmony session token.
Harmony session token .
ip
string
IP address of the Harmony Hub.
IP address of the Harmony Hub .
username
string
None
password
string
None
bypassLogitech
bool
None