innoQ

Vladimir's Tech Blog


Cutting corners with xmpp4r-simple

July 3, 2008

xmpp4r-simple aims to provide a wrapper around the powerful and well maintained xmpp4r library, "making it dead-simple to send and receive Jabber messages".

Unfortunately, the abstraction and simplification provided by xmpp4r-simple is leaky, missing the principles of jabber protocol. The result - the naive implementation (from the tutorial) did not work for me:

# Send a message to a friend, asking for authorization if necessary:
im = Jabber::Simple.new("[email protected]", "password")
im.deliver("[email protected]", "Hey there friend!")

Yes, I did replace the example.com with the name of my server. ;-)

Result - response 406 "Not Acceptable"

The problem

Jabber::ClientAuthenticationFailure: : Not Acceptable
from /usr/lib/ruby/gems/1.8/gems/xmpp4r-0.3.2.99/lib/xmpp4r/client.rb:116:in `auth'
from /usr/lib/ruby/gems/1.8/gems/xmpp4r-simple-0.8.7/lib/xmpp4r-simple.rb:391:in `connect!'
from /usr/lib/ruby/gems/1.8/gems/xmpp4r-simple-0.8.7/lib/xmpp4r-simple.rb:322:in `client'
from /usr/lib/ruby/gems/1.8/gems/xmpp4r-simple-0.8.7/lib/xmpp4r-simple.rb:331:in `send!'
from /usr/lib/ruby/gems/1.8/gems/xmpp4r-simple-0.8.7/lib/xmpp4r-simple.rb:147:in `status'
from /usr/lib/ruby/gems/1.8/gems/xmpp4r-simple-0.8.7/lib/xmpp4r-simple.rb:90:in `initialize'
from (irb):3:in `new'
from (irb):3

The trace

So I had to go couple of abstraction layers deeper to get it running. At the end I am glad about that. The best opportunity to learn a protocol - to read the documentation in connection with the problem at hand and by observing the actual communication.

Using Gajim's XML Console you can trace the communication between the client and the server:

Client: connecting...

<iq type="get" id="29">
  <query xmlns="jabber:iq:auth">
    <username>johndoe</username>
  </query>
</iq>

Server tells, which information the client should provide:

<iq type='result' id='29'>
  <query xmlns='jabber:iq:auth'>
    <username>johndoe</username>
    <digest/>
    <password/>
    <resource/>
  </query>
</iq>

Client fills in the blanks providing the needed information:

<iq type="set" id="30">
  <query xmlns="jabber:iq:auth">
    <username>johndoe</username>
    <digest>c26789d0exyz4adf8c61e62e8fef27e6d0de</digest>
    <resource>Gajim</resource>
  </query>
</iq>

Server: connection succeeded:

My server is a jabberd14 (the original reference implementation of the Jabber protocol), easily installable on Ubuntu by sudo aptitude install jabber.

As seen in the log, it requires the resource-clause - some sort of subnamespace. Gajim and Pidgin and probably all other Clients are smart enough to provide it if requested by the server. xmpp4r-simple is not.

The solution

The solution was to provide the required information from the beginning on, because xmpp4r ignores the Jabber typical handshake. Please note the /Home after the jabber id.

im = Jabber::Simple.new("[email protected]/Home", "password")
im.deliver("[email protected]", "Hey there friend!")

Read more about the Jabber communication protocoll.

Trackback Pings

TrackBack URL for this entry:
http://www.innoq.com/movabletype/mt-tb.cgi/3053

Comments

Post a comment




Remember Me?


Powered by Movable Type 3.31