Not logged in. · Lost password · Register
Forum: agsXMPP RSS
Avatar
akhhttar #1
Member since Aug 2012 · 11 posts
Group memberships: Members
Show profile · Link to this post
Subject: 'Stack Empty' Exception after successfully login.
Hi Everyone,

I am using agsXmpp Library to connect with Windows Live XMPP Service. I am able to connect and authenticate the user but then I receive 'Empty Stack' exception. I need help to identify the reason.

Here is my code and logs:

Code:
  1.  
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Text;
  5. using agsXMPP;
  6. using agsXMPP.protocol.client;
  7. using agsXMPP.Collections;
  8. using agsXMPP.protocol.iq.roster;
  9. using System.Threading;
  10.  
  11. namespace JabberClient
  12. {
  13.     class Program
  14.     {
  15.         static bool _wait;
  16.         static XmppClientConnection xmpp = new XmppClientConnection();
  17.      
  18.         static void Main(string[] args)
  19.         {
  20.          
  21.             xmpp.ConnectServer = "xmpp.messenger.live.com";
  22.             xmpp.Server = "messenger.live.com";
  23.             xmpp.UseStartTLS = true;
  24.             xmpp.AutoRoster = true;
  25.             xmpp.AutoPresence = true;
  26.             xmpp.Port = 5222;
  27.  
  28.             try
  29.             {
  30.                
  31.                
  32.                 xmpp.OnSaslStart += new agsXMPP.Sasl.SaslEventHandler(xmpp_OnSaslStart);
  33.                 xmpp.OnStreamError += new XmppElementHandler(xmpp_OnStreamError);
  34.                 xmpp.OnError += new ErrorHandler(xmpp_OnError);
  35.                 xmpp.OnReadXml += new XmlHandler(xmpp_OnReadXml);
  36.                 xmpp.OnWriteXml += new XmlHandler(xmpp_OnWriteXml);
  37.                 xmpp.OnAuthError += new XmppElementHandler(xmpp_OnAuthError);
  38.                 xmpp.OnClose += new ObjectHandler(xmpp_OnClose);
  39.              
  40.                
  41.                 xmpp.Open();
  42.                 xmpp.OnLogin += new ObjectHandler(xmpp_OnLogin);
  43.             }
  44.             catch (Exception e)
  45.             {
  46.                 Console.WriteLine(e.Message);
  47.             }
  48.  
  49.            
  50.             Console.ReadLine();
  51.  
  52.            
  53.             xmpp.Close();
  54.         }
  55.  
  56.         static void xmpp_OnStreamError(object sender, agsXMPP.Xml.Dom.Element e)
  57.         {
  58.            
  59.         }
  60.  
  61.         static void xmpp_OnClose(object sender)
  62.         {
  63.             Console.WriteLine("OnClose");
  64.             if (redirect)
  65.                 xmpp.Open();
  66.             redirect = false;
  67.         }
  68.  
  69.         static void xmpp_OnAuthError(object sender, agsXMPP.Xml.Dom.Element e)
  70.         {
  71.             Console.WriteLine("OnAuthrError");
  72.         }
  73.  
  74.         static void xmpp_OnWriteXml(object sender, string xml)
  75.         {
  76.             Console.WriteLine("WriteXml:");
  77.             Console.WriteLine(xml);
  78.         }
  79.  
  80.         static void xmpp_OnReadXml(object sender, string xml)
  81.         {
  82.             Console.WriteLine("ReadXml:");
  83.             Console.WriteLine(xml);
  84.             if (xml.Contains("see-other-host"))
  85.             {
  86.                 System.Xml.XmlDocument d = new System.Xml.XmlDocument();
  87.                 d.LoadXml(xml);
  88.                 xmpp.ConnectServer = d.DocumentElement.GetElementsByTagName("see-other-host")[0].InnerText;
  89.                 xmpp.AutoResolveConnectServer = false;
  90.                 xmpp.Port = 5222;
  91.                 redirect = true;
  92.             }
  93.         }
  94.  
  95.         static void xmpp_OnError(object sender, Exception ex)
  96.         {
  97.             Console.WriteLine("OnError");
  98.             Console.WriteLine(ex.Message);
  99.  
  100.         }
  101.  
  102.         static void xmpp_OnXmppError(object sender, agsXMPP.Xml.Dom.Element e)
  103.         {
  104.             Console.WriteLine("OnXmppError");
  105.             Console.WriteLine(e.Value);
  106.         }
  107.  
  108.         static void xmpp_OnSaslStart(object sender, agsXMPP.Sasl.SaslEventArgs args)
  109.         {
  110.             args.Auto = false;
  111.             var auth = new agsXMPP.protocol.sasl.Auth();
  112.             auth.Attributes.Add("mechanism", "X-MESSENGER-OAUTH2");
  113.             auth.Value = "EwA4Aq1DBAAUlbRWyAJjK5w968Ru3Cyt/6GvwXwAAaftsJebekJdR3Bc44NP4ub51GcHbJgPWTB1pxljZshErHMd5Vph9wSDQMyx3Tewnhn4tGCDx6lN0G56cQXJYvMpere7hoMu74TUiT+hrXpOKmUhcpcqQlX9v5H2nOj+uApAREtU8gQ1zsbXTVl6ENMBjhZU05rM3T7iZQARjoTC/kmwJHzV70h0GcGc5fP0gW1gdGXQUxYzem5E1LKJBwseVMFtea+66bZruMrmFJvs25XKNVksKCj6tuYBal7WkGvqiXugirfO7aT7U/WCtdhCgPYjp6YN8LYyhzp2D/qPhzjJNS2xNwP2v0bY2l1lZKz7eAYfKNlhyiJDVuoi0xADZgAACMKgxwEQvtn1CAGPdP4Xlfmx4Yb7SX3tDXPCpFnv6U1APCjogz79OqWpRJ0EPAVWWVN91Sb9EwDmSPML9mvnYN2zQU45ywhDaq86dVYrRMYPyzs6/ChMtSr4V6Q9qYg32MsSCdfyl4SxxCVvT89NSuncyYZjOojLTUiD9YiIxSbdud+/BMkeHcZvuKGyxqynkQMRUqTbiCu6HfQBIHpN1HNLmILsnYnNYDARHRftdm0WBKCRp8JlF+fupRBqypz73KXzNzsteymsHwvCMQZ/vAPDDmfkoGYyDvKibuwtoeCP2ZV5Zb2681QX4zzQ6jeRFaM7hMj4E5Ekw7VzXUUMf2IeG0Nf7Iq/tG/chpiG0d1Vps8AAA==";
  114.             xmpp.Send(auth);
  115.  
  116.         }
  117.  
  118.         // Is called, if the precence of a roster contact changed       
  119.         static void xmpp_OnPresence(object sender, Presence pres)
  120.         {
  121.             Console.WriteLine("Available Contacts: ");
  122.             Console.WriteLine("{0}@{1}  {2}", pres.From.User, pres.From.Server, pres.Type);
  123.             //Console.WriteLine(pres.From.User + "@" + pres.From.Server + "  " + pres.Type);
  124.             Console.WriteLine();
  125.         }
  126.  
  127.         // Is raised when login and authentication is finished
  128.         static void xmpp_OnLogin(object sender)
  129.         {
  130.             _wait = false;
  131.             Console.WriteLine("Logged In");
  132.         }
  133.  
  134.         //Handles incoming messages
  135.         static void MessageCallBack(object sender,
  136.                                     agsXMPP.protocol.client.Message msg,
  137.                                     object data)
  138.         {
  139.             if (msg.Body != null)
  140.             {
  141.                 Console.ForegroundColor = ConsoleColor.Red;
  142.                 Console.WriteLine("{0}>> {1}", msg.From.User, msg.Body);
  143.                 Console.ForegroundColor = ConsoleColor.Green;
  144.             }
  145.         }
  146.  
  147.         public static bool redirect { get; set; }
  148.     }
  149. }

Logs:


WriteXml:
<stream:stream to='messenger.live.com' xmlns='jabber:client' xmlns:stream='http:
//etherx.jabber.org/streams' version='1.0' xml:lang='en'>
ReadXml:
<stream:stream xmlns:stream="http://etherx.jabber.org/streams" from="messenger.l
ive.com" version="1.0" id="38428" >
ReadXml:
<stream:features xmlns:stream="http://etherx.jabber.org/streams"><starttls xmlns
="urn:ietf:params:xml:ns:xmpp-tls"><required /></starttls></stream:features>
WriteXml:
<starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls" />
ReadXml:
<proceed xmlns="urn:ietf:params:xml:ns:xmpp-tls" />
WriteXml:
<stream:stream to='messenger.live.com' xmlns='jabber:client' xmlns:stream='http:
//etherx.jabber.org/streams' version='1.0' xml:lang='en'>
ReadXml:
<stream:stream xmlns:stream="http://etherx.jabber.org/streams" from="messenger.l
ive.com" version="1.0" id="38430" >
ReadXml:
<stream:error xmlns:stream="http://etherx.jabber.org/streams"><see-other-host xm
lns="urn:ietf:params:xml:ns:xmpp-streams">BAYMSG1020414.gateway.messenger.live.c
om</see-other-host></stream:error>
ReadXml:
</stream:stream>
OnClose
WriteXml:
<stream:stream to='messenger.live.com' xmlns='jabber:client' xmlns:stream='http:
//etherx.jabber.org/streams' version='1.0' xml:lang='en'>
ReadXml:
<stream:stream xmlns:stream="http://etherx.jabber.org/streams" from="messenger.l
ive.com" version="1.0" id="78742" >
ReadXml:
<stream:features xmlns:stream="http://etherx.jabber.org/streams"><starttls xmlns
="urn:ietf:params:xml:ns:xmpp-tls"><required /></starttls></stream:features>
WriteXml:
<starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls" />
ReadXml:
<proceed xmlns="urn:ietf:params:xml:ns:xmpp-tls" />
WriteXml:
<stream:stream to='messenger.live.com' xmlns='jabber:client' xmlns:stream='http:
//etherx.jabber.org/streams' version='1.0' xml:lang='en'>
ReadXml:
<stream:stream xmlns:stream="http://etherx.jabber.org/streams" from="messenger.l
ive.com" version="1.0" id="78743" >
ReadXml:
<stream:features xmlns:stream="http://etherx.jabber.org/streams"><mechanisms xml
ns="urn:ietf:params:xml:ns:xmpp-sasl"><mechanism>X-MESSENGER-OAUTH2</mechanism><
/mechanisms></stream:features>
WriteXml:
<auth xmlns="urn:ietf:params:xml:ns:xmpp-sasl" mechanism="X-MESSENGER-OAUTH2">Ew
A4Aq1DBAAUlbRWyAJjK5w968Ru3Cyt/6GvwXwAAaftsJebekJdR3Bc44NP4ub51GcHbJgPWTB1pxljZs
hErHMd5Vph9wSDQMyx3Tewnhn4tGCDx6lN0G56cQXJYvMpere7hoMu74TUiT+hrXpOKmUhcpcqQlX9v5
H2nOj+uApAREtU8gQ1zsbXTVl6ENMBjhZU05rM3T7iZQARjoTC/kmwJHzV70h0GcGc5fP0gW1gdGXQUx
Yzem5E1LKJBwseVMFtea+66bZruMrmFJvs25XKNVksKCj6tuYBal7WkGvqiXugirfO7aT7U/WCtdhCgP
Yjp6YN8LYyhzp2D/qPhzjJNS2xNwP2v0bY2l1lZKz7eAYfKNlhyiJDVuoi0xADZgAACMKgxwEQvtn1CA
GPdP4Xlfmx4Yb7SX3tDXPCpFnv6U1APCjogz79OqWpRJ0EPAVWWVN91Sb9EwDmSPML9mvnYN2zQU45yw
hDaq86dVYrRMYPyzs6/ChMtSr4V6Q9qYg32MsSCdfyl4SxxCVvT89NSuncyYZjOojLTUiD9YiIxSbdud
+/BMkeHcZvuKGyxqynkQMRUqTbiCu6HfQBIHpN1HNLmILsnYnNYDARHRftdm0WBKCRp8JlF+fupRBqyp
z73KXzNzsteymsHwvCMQZ/vAPDDmfkoGYyDvKibuwtoeCP2ZV5Zb2681QX4zzQ6jeRFaM7hMj4E5Ekw7
VzXUUMf2IeG0Nf7Iq/tG/chpiG0d1Vps8AAA==</auth>
WriteXml:
<iq id="agsXMPP_1" type="get" to="messenger.live.com"><query xmlns="jabber:iq:au
th"><username /></query></iq>
ReadXml:
<success xmlns="urn:ietf:params:xml:ns:xmpp-sasl" />
WriteXml:
<stream:stream to='messenger.live.com' xmlns='jabber:client' xmlns:stream='http:
//etherx.jabber.org/streams' version='1.0' xml:lang='en'>
OnClose
OnClose
OnError
Stack empty.

Thanks
-Akhtar
This post was edited on 2012-09-20, 21:09 by Alex.
Avatar
Alex #2
Member since Feb 2003 · 4322 posts · Location: Germany
Group memberships: Administrators, Members
Show profile · Link to this post
after the auth tag the following is sent to the server:

  1. <iq id="agsXMPP_1" type="get" to="messenger.live.com">
  2.    <query xmlns="jabber:iq:auth">
  3.       <username />
  4.    </query>
  5. </iq>

The problem is caused by your code in the OnSaslStart event.
You have to create a new Sasl mechanism by inheriting from Mechanism and registering it in the SaslFactory.

Alex
Avatar
akhhttar #3
Member since Aug 2012 · 11 posts
Group memberships: Members
Show profile · Link to this post
Thank you Alex for your quick response ( as usual :))

As per your suggestion, I have resolved the issue by creating a new SASLMechanism class for windows Live.

Thanks
-Akhtar
Avatar
Alex #4
Member since Feb 2003 · 4322 posts · Location: Germany
Group memberships: Administrators, Members
Show profile · Link to this post
Great, maybe you can share your code here with other users as well.

Alex
Avatar
akhhttar #5
Member since Aug 2012 · 11 posts
Group memberships: Members
Show profile · Link to this post
Sure.

I have made three changes in above code to make it work,

1. Created a new Sasl Mechanism class derived for agsXMPP.Sasl.Mechanism. Override the Init method and send the Sasl Authentication request with Access Token.


 public class WindowsLiveSaslMechanism : agsXMPP.Sasl.Mechanism
    {

        public override void Init(XmppClientConnection con)
        {
            var auth = new agsXMPP.protocol.sasl.Auth();
            auth.Attributes.Add("mechanism", "X-MESSENGER-OAUTH2");
            //I have hard codedly provided the Access Token for testing purpose, you can use any method to get/generate the access token at this level.
            auth.Value = "EwA4Aq1DBAAUlbRWyAJjK5w968Ru3Cyt/6............c9yZffAAAA==";
            con.Send(auth);
        }

        public override void Parse(agsXMPP.Xml.Dom.Node e)
        {
          
        }
    }

2. Register the new Sasl class with SaslFactory at the start of the program


 SaslFactory.AddMechanism("X-MESSENGER-OAUTH2", typeof(WindowsLiveSaslMechanism));

3. Modify the OnStartSasl event to set the Sasl Mechanism name


  static void xmpp_OnSaslStart(object sender, agsXMPP.Sasl.SaslEventArgs args)
        {
            args.Auto = false;
            args.Mechanism = "X-MESSENGER-OAUTH2";
        
            //Note: I think there should be some method here to passs the access token to Sasl Class.
        }


Here is the complete code ( my code can definitely be much much much better, I am posting my POC as it is :))


using System;
using System.Collections.Generic;
using System.Text;
using agsXMPP;
using agsXMPP.protocol.client;
using agsXMPP.Collections;
using agsXMPP.protocol.iq.roster;
using System.Threading;
using agsXMPP.Factory;

namespace JabberClient
{
    class Program
    {
        static bool _wait;
        static XmppClientConnection xmpp = new XmppClientConnection();
    
        static void Main(string[] args)
        {
            SaslFactory.AddMechanism("X-MESSENGER-OAUTH2", typeof(WindowsLiveSaslMechanism));
         
            xmpp.ConnectServer = "xmpp.messenger.live.com";
            xmpp.Server = "messenger.live.com";
            xmpp.UseStartTLS = true;
            xmpp.AutoRoster = true;
            xmpp.AutoPresence = true;
            xmpp.Port = 5222;
         
            try
            {
              
              
                xmpp.OnSaslStart += new agsXMPP.Sasl.SaslEventHandler(xmpp_OnSaslStart);
                xmpp.OnStreamError += new XmppElementHandler(xmpp_OnStreamError);
                xmpp.OnError += new ErrorHandler(xmpp_OnError);
                xmpp.OnReadXml += new XmlHandler(xmpp_OnReadXml);
                xmpp.OnWriteXml += new XmlHandler(xmpp_OnWriteXml);
                xmpp.OnAuthError += new XmppElementHandler(xmpp_OnAuthError);
                xmpp.OnClose += new ObjectHandler(xmpp_OnClose);


                xmpp.Open();
                xmpp.OnLogin += new ObjectHandler(xmpp_OnLogin);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }

           
            Console.ReadLine();

           
            xmpp.Close();
        }

        static void xmpp_OnStreamError(object sender, agsXMPP.Xml.Dom.Element e)
        {
          
        }

        static void xmpp_OnClose(object sender)
        {
            Console.WriteLine("OnClose");
            if (redirect)
                xmpp.Open();
            redirect = false;
        }

        static void xmpp_OnAuthError(object sender, agsXMPP.Xml.Dom.Element e)
        {
            Console.WriteLine("OnAuthrError");
        }

        static void xmpp_OnWriteXml(object sender, string xml)
        {
            Console.WriteLine("WriteXml:");
            Console.WriteLine(xml);
        }

        static void xmpp_OnReadXml(object sender, string xml)
        {
            Console.WriteLine("ReadXml:");
            Console.WriteLine(xml);
            if (xml.Contains("see-other-host"))
            {
                System.Xml.XmlDocument d = new System.Xml.XmlDocument();
                d.LoadXml(xml);
                xmpp.ConnectServer = d.DocumentElement.GetElementsByTagName("see-other-host")[0].InnerText;
                xmpp.AutoResolveConnectServer = false;
                xmpp.Port = 5222;
                redirect = true;
            }
        }

        static void xmpp_OnError(object sender, Exception ex)
        {
            Console.WriteLine("OnError");
            Console.WriteLine(ex.Message);

        }

        static void xmpp_OnXmppError(object sender, agsXMPP.Xml.Dom.Element e)
        {
            Console.WriteLine("OnXmppError");
            Console.WriteLine(e.Value);
        }

        static void xmpp_OnSaslStart(object sender, agsXMPP.Sasl.SaslEventArgs args)
        {
            args.Auto = false;
            args.Mechanism = "X-MESSENGER-OAUTH2";
        
            //Note: I think there should be some method here to passs the access token to Sasl Class.
        }

        // Is called, if the precence of a roster contact changed       
        static void xmpp_OnPresence(object sender, Presence pres)
        {
            Console.WriteLine("Available Contacts: ");
            Console.WriteLine("{0}@{1}  {2}", pres.From.User, pres.From.Server, pres.Type);
            //Console.WriteLine(pres.From.User + "@" + pres.From.Server + "  " + pres.Type);
            Console.WriteLine();
        }

        // Is raised when login and authentication is finished
        static void xmpp_OnLogin(object sender)
        {
            _wait = false;
            Console.WriteLine("Logged In");
        }

        //Handles incoming messages
        static void MessageCallBack(object sender,
                                    agsXMPP.protocol.client.Message msg,
                                    object data)
        {
            if (msg.Body != null)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine("{0}>> {1}", msg.From.User, msg.Body);
                Console.ForegroundColor = ConsoleColor.Green;
            }
        }

        public static bool redirect { get; set; }
    }

    public class WindowsLiveSaslMechanism : agsXMPP.Sasl.Mechanism
    {

    
        public override void Init(XmppClientConnection con)
        {
            var auth = new agsXMPP.protocol.sasl.Auth();
            auth.Attributes.Add("mechanism", "X-MESSENGER-OAUTH2");
            //I have hard codedly provided the Access Token for testing purpose, you can use any method to get/generate the access token at this level.
            auth.Value = "EwA4Aq1DBAAUlbRWyAJjK5w968Ru3C------wc9yZffAAAA==";
            con.Send(auth);
        }

        public override void Parse(agsXMPP.Xml.Dom.Node e)
        {
          
        }
    }
}

Thank You
-Akhtar
Avatar
Alex #6
Member since Feb 2003 · 4322 posts · Location: Germany
Group memberships: Administrators, Members
Show profile · Link to this post
I have added a Token property to Mechanism and SaslEventArgs.
This allows you now to pass the Token from the Event in the event args to your Sasl Mechanism.
Please check out the latest sources and give it a try.

Alex
Avatar
akhhttar #7
Member since Aug 2012 · 11 posts
Group memberships: Members
Show profile · Link to this post
Thank you very much for your GREAT support :).

I am not able to connect with the your SVN repository form my home. It seems that my ISP has blocked the domain name ag-software.de. I am also using your website using proxy. I will try get he latest code from my office.

Thanks again for your help.
-Akhtar
Avatar
Alex #8
Member since Feb 2003 · 4322 posts · Location: Germany
Group memberships: Administrators, Members
Show profile · Link to this post
SVN Uri is: svn://svn.ag-software.de/agsxmpp
Close Smaller – Larger + Reply to this post:
Verification code: VeriCode Please enter the word from the image into the text field below. (Type the letters only, lower case is okay.)
Smileys: :-) ;-) :-D :-p :blush: :cool: :rolleyes: :huh: :-/ <_< :-( :'( :#: :scared: 8-( :nuts: :-O
Special characters:
Forum: agsXMPP RSS