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("firstname.lastname@example.org", "password") im.deliver("email@example.com", "Hey there friend!")
Yes, I did replace the
example.com with the name of my server. ;-)
Result - response 406 "Not Acceptable"
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
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:
<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
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 was to provide the required information from the beginning
on, because xmpp4r ignores the Jabber typical handshake. Please
/Home after the jabber id.
im = Jabber::Simple.new("firstname.lastname@example.org/Home", "password") im.deliver("email@example.com", "Hey there friend!")
TrackBack URL for this entry: