Not logged in. · Lost password · Register
Forum: agsXMPP RSS
Avatar
ted #1
Member since Apr 2009 · 4 posts
Group memberships: Members
Show profile · Link to this post
Subject: Synchronous IQ with IqGrabber
Hi,

I have a question regarding the IqGrabber, as I am not sure, if I got something wrong there.

As I am in need of synchronous IQs I took a look into documentation and found the IqGrabber, offering a sendIq-Method without taking a CB-function and returning an IQ. Description says: "Sends an Iq synchronous and return the response or null on timeout". What I get till now is always null. So is this generally possible or do I misunderstand anything?

My Code looks like this:
DiscoItemsIq discoIq = new DiscoItemsIq(IqType.get);
discoIq.To = new Jid("pubsub.example.com");
discoIq.From = new Jid(JID_SENDER);
IQ itemList = con.IqGrabber.SendIq(discoIq, 5000);
Console.WriteLine(itemList.ToString());

And the generated IQ-XML sent to the server:
<iq id="agsXMPP_4" type="get" to="pubsub.example.com" from="ted@example.com">
<query xmlns="http://jabber.org/protocol/disco#items" />
</iq>

BTW: Wenn using sendIq() with a specified callback function, I get a valid return.

Greetings,
Ted
Avatar
Alex #2
Member since Feb 2003 · 4327 posts · Location: Germany
Group memberships: Administrators, Members
Show profile · Link to this post
Hi Ted,

this is correct. I added the following code to a command button in the MiniClien exampel and it works without problems:

  1. DiscoItemsIq discoIq = new DiscoItemsIq(IqType.get);
  2. discoIq.To = new Jid("ag-software.de");
  3. IQ res = XmppCon.IqGrabber.SendIq(discoIq, 5000);
  4. Console.WriteLine(res.ToString());

during my test I am connected to our xmpp sever at ag-software.de

The only difference I see in your code is the From property. Never use the From in a client. Unlike in other protocols you can't spoof the from address in XMPP. The server always stamps the from address for you.

Alex
Avatar
ted #3
Member since Apr 2009 · 4 posts
Group memberships: Members
Show profile · Link to this post
Hi Alex,

thank you for your time.

I found out, that the synchronous Grabber won`t work, when using an OnLogin-Handler.

In my code it looks like this:

xmpp.OnLogin += new ObjectHandler(xmppCon_OnLogin);

private void xmppCon_OnLogin(object sender)
        {
            Console.WriteLine("logged in to server");
            doSomething();
        }

public void doSomething()
        {
                DiscoItemsIq discoIq = new DiscoItemsIq(IqType.get);
                discoIq.To = new Jid(receiver);
                String baseNode = "someQuery";
                discoIq.Query.SetAttribute("node", baseNode);
                IQ iq = xmpp.IqGrabber.SendIq(discoIq, 5000);
        }

The query gets sent to the server as I can see in the console. But as I said, no iq from the server will be received.
I have no idea, why. Am I missing something?

Greetings,
Ted
Avatar
Alex #4
Member since Feb 2003 · 4327 posts · Location: Germany
Group memberships: Administrators, Members
Show profile · Link to this post
Some servers don't respond to IQs until you have sent you own presence to the server. In this case the OnLogin handler is to early.
Try to send you presence to the server first.

If this does not help please post the complete Xml log of the session.

Alex
Avatar
ted #5
Member since Apr 2009 · 4 posts
Group memberships: Members
Show profile · Link to this post
I tried to send my presence first, but that didnt help.

The servers response seems to get stuck anywhere in the client, as I saw it being written to the console two minutes later after other messages already have been processed.

I added a xml logger to my ejabberd.
As you can see, the server responds immediately to the Iq:

<packet or="recv" ljid="ted@myserver.com/agsXMPP" ts="20090409T01:35:10">
    <presence from='ted@myserver.com/agsXMPP' to='ted@myserver.com/agsXMPP' xml:lang='en'>
        <show>xa</show>
        <status/>
        <priority>5</priority>
        </presence>
    </packet>
<packet or="send" ljid="ted@myserver.com/agsXMPP" ts="20090409T01:35:10">
    <iq xml:lang='en' id='agsXMPP_3' type='get' to='pubsub.myserver.com'>
        <query xmlns='http://jabber.org/protocol/disco#items' node='home/myserver.com/ted'/>
    </iq>
</packet>
<packet or="recv" ljid="ted@myserver.com/agsXMPP" ts="20090409T01:35:10">
    <iq from='pubsub.myserver.com' to='ted@myserver.com/agsXMPP' id='agsXMPP_3' type='result'>
        <query xmlns='http://jabber.org/protocol/disco#items' node='home/myserver.com/ted'>
            <item jid='pubsub.myserver.com' node='/home/myserver.com/ted/test' name='test'/>
            <item jid='pubsub.myserver.com' node='/home/myserver.com/ted/test2' name='test2'/>
        </query>
    </iq>
</packet>

And here is the log from my client:


<stream:stream to='myserver.com' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0' xml:lang='en'>
<stream:stream xmlns:stream="http://etherx.jabber.org/streams" from="myserver.com" version="1.0" xml:lang="en" id="1981579862" >
<stream:features xmlns:stream="http://etherx.jabber.org/streams">
    <starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls" />
    <mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl">
        <mechanism>DIGEST-MD5</mechanism>
        <mechanism>PLAIN</mechanism>
    </mechanisms>
    <register xmlns="http://jabber.org/features/iq-register" />
</stream:features>
<starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls" />
<proceed xmlns="urn:ietf:params:xml:ns:xmpp-tls" />
<stream:stream to='myserver.com' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0' xml:lang='en'>
<stream:stream xmlns:stream="http://etherx.jabber.org/streams" from="myserver.com" version="1.0" xml:lang="en" id="1906520463" >
<stream:features xmlns:stream="http://etherx.jabber.org/streams">
    <mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl">
        <mechanism>DIGEST-MD5</mechanism>
        <mechanism>PLAIN</mechanism>
    </mechanisms>
    <register xmlns="http://jabber.org/features/iq-register" />
</stream:features>
<auth xmlns="urn:ietf:params:xml:ns:xmpp-sasl" mechanism="DIGEST-MD5" />
<challenge xmlns="urn:ietf:params:xml:ns:xmpp-sasl">bm[...]3M=</challenge>
<response xmlns="urn:ietf:params:xml:ns:xmpp-sasl">dX[...]jUx</response>
<challenge xmlns="urn:ietf:params:xml:ns:xmpp-sasl">cn[...]g==</challenge>
<response xmlns="urn:ietf:params:xml:ns:xmpp-sasl" />
<success xmlns="urn:ietf:params:xml:ns:xmpp-sasl" />
<stream:stream to='myserver.com' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0' xml:lang='en'>
<stream:stream xmlns:stream="http://etherx.jabber.org/streams" from="myserver.com" version="1.0" xml:lang="en" id="439118914" >
<stream:features xmlns:stream="http://etherx.jabber.org/streams"><bind xmlns="urn:ietf:params:xml:ns:xmpp-bind" />
    <session xmlns="urn:ietf:params:xml:ns:xmpp-session" />
</stream:features>
<iq id="agsXMPP_1" type="set" to="myserver.com">
    <bind xmlns="urn:ietf:params:xml:ns:xmpp-bind">
        <resource>agsXMPP</resource>
    </bind>
</iq>
<iq xmlns="jabber:client" type="result" id="agsXMPP_1">
    <bind xmlns="urn:ietf:params:xml:ns:xmpp-bind">
        <jid>ted@myserver.com/agsXMPP</jid>
    </bind>
</iq>
<iq id="agsXMPP_2" type="set" to="myserver.com">
    <session xmlns="urn:ietf:params:xml:ns:xmpp-session" />
</iq>
<iq xmlns="jabber:client" from="myserver.com" type="result" id="agsXMPP_2">
<session xmlns="urn:ietf:params:xml:ns:xmpp-session" />
</iq>
OnLoginHandler called!
<presence>
    <show>xa</show>
    <status />
    <priority>5</priority>
</presence>
<iq id="agsXMPP_3" type="get" to="pubsub.myserver.com">
    <query xmlns="http://jabber.org/protocol/disco#items" node="home/myserver.com/ted" />
</iq>

In case you want to try for yourself, I added the modified ConsoleClient example which shows the described behaviour.

Greetings,
Ted
The author has attached one file to this post:
ConsoleClient.rar 399 kBytes
You have no permission to open this file.
This post was edited on 2009-04-09, 15:38 by ted.
Avatar
Alex #6
Member since Feb 2003 · 4327 posts · Location: Germany
Group memberships: Administrators, Members
Show profile · Link to this post
You cannot do a synchronous call from a asynchronous agsXMPP event. This will block the parser thread, and is the reason why it does not work.

I modified your code to the following and it works:
  1. void xmppCon_OnPresence(object sender, Presence pres)
  2. {
  3.     PrintInfo(String.Format("Got presence from: {0}", pres.From.ToString()));
  4.     PrintInfo(String.Format("type: {0}", pres.Type.ToString()));
  5.     PrintInfo(String.Format("status: {0}", pres.Status));
  6.     PrintInfo("");   
  7.  
  8.     Thread newThread = new Thread(new ThreadStart(PubSubDisco));
  9.     newThread.Start();               
  10. }
  11.  
  12. void PubSubDisco()
  13. {
  14.     DiscoItemsIq discoIq = new DiscoItemsIq(IqType.get);
  15.  
  16.     discoIq.To = new Jid("pubsub@ag-software.de");
  17.     String baseNode = "home/myserver.com/ted";
  18.     discoIq.Query.SetAttribute("node", baseNode);
  19.     IQ iq = xmppCon.IqGrabber.SendIq(discoIq, 50000);
  20.  
  21.     Console.WriteLine(iq.ToString());
  22. }

You can add synchronous code to the the ConsoleClient pretty easy with AutoResetEvents
Avatar
ted #7
Member since Apr 2009 · 4 posts
Group memberships: Members
Show profile · Link to this post
Hi Alex,

thanks a lot! That solved my problem.
I should take a deeper look into Threading...

Greetings and keep up the good work,
Ted
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