[JDEV] Trouble in making my own JUD component in Jabber

DJ Adams dj.adams at pobox.com
Tue Nov 6 14:25:32 CST 2001


On Tue, Nov 06, 2001 at 01:53:15PM +0800, Migs Paraz wrote:
> I resolved the previous problem - it was mismatched secrets - and I'm
> getting the hang of using Jabber::Nodefactory.  I wrote this little piece
> of code to start off writing a JUD component/transport; I'm looking into
> writing other sorts of transports later.
> 
> This one is supposed to give the list of search keys to a Jabber client.
> I followed the jabber-programmers.pdf file.
> 
> But, when testing with Gabber, it just waits on the server.  What is wrong?
> Malformed output?  Thanks.

Hi Migs

The problem is that you're not specifying a to='...' in your reply. It's
getting dropped by the Jabber server as invalid... 

I've put in a few comments in the code.  By adding the line indicated,
your script will work as intended. I've also given an alternative way
of doing things at the end of this mail...

> #!/usr/bin/perl
> # juday.pl, a JUD component
> 
> use Jabber::Connection;
> use Jabber::NodeFactory;
> use Jabber::NS qw(:all);
> 
> our $c = new Jabber::Connection(
>   ns => "jabber:component:accept",                             
>   server => 'localhost:1234',
>   localname => "jud.localhost",
>   log    => 1,
> );
> 
> $c->connect or die "oops: ".$c->lastError;
> $c->register_handler('message', \&message);
> $c->register_handler('iq', \&iq);
> 
> $c->auth("test");
> 
> # I wonder if this is needed for components.
> $c->send('<presence/>');

No, it's not. Well, <presence/> as a concept is still valid within
components, but you have to program for it, and sending it here 
doesn't make much sense. There is, however, an idiom that involves
sending presence when connecting as a client; this reflects the 
difference in that the connection as a client is to the JSM, which
has the mod_presence handler to handle presence diffusion (love that
word here :-) for you. 

> 
> 
> $c->start();
> 
> $c->disconnect();
> 
> 
> sub message {
>   my $node = shift;
>   print "Message --> ", $node->toStr, "\n";
> }
> 
> sub iq {
>   my $node = shift;
> 
>   print "IQ --> ", $node->toStr(), "\n";
> 
>   # Different kinds of XML content
>   if (($node->attr("type") eq "get") &&
>       ($node->getTag("query", "jabber:iq:search"))) {

As you've imported all the constants from Jabber:NS, you can use constants
in the above two lines (and in the one a bit further down), like this:

    if (($node->attr("type") eq IQ_GET) &&
        ($node->getTag("query", NS_SEARCH))) {

>       my $id = $node->attr("id");
> 
>       # Request for search parameters.
>       my $nf = new Jabber::NodeFactory;
> 
>       my $tag = $nf->newNode("iq");
>       $tag->attr("type", "result");
>       $tag->attr("from", "jud.localhost");

Add this line to make this script work as intended:

        $tag->attr("to", $node->attr("from"));

>       $tag->attr("id", $id);
>       
>       my $tag2 = $tag->insertTag("query", "jabber:iq:search");
>       $tag2->insertTag("first");
>       $tag2->insertTag("last");
>       $tag2->insertTag("nick");
>       $tag2->insertTag("email");
> 
>       # I wonder if this key is needed.
>       $tag2->insertTag("key")->data("1");

Well, only if you're going to test for it when the IQ-set comes back. 
<key>s are really a throwback to the pre-dialback days ...

> 
>       $tag2->insertTag("instructions")->data("juday is here to help.");
> 
>       # Send back to client
>       $c->send($tag);
>   }
> }
> 

Taking a leaf out of the jabber.org server source's book, another way of 
responding to requests is to just munge the incoming request into your
desired reply. It depends on what you feel comfortable with doing, but
here's an example alternative version of the reply bit:

  if (($node->attr("type") eq IQ_GET) &&
      (my $query = $node->getTag("", NS_SEARCH))) {
 
      $node->attr("type", "result");
      my $to = $node->attr('to');
      $node->attr('to', $node->attr('from'));
      $node->attr('from', $to);
 
      $query->insertTag("first");
      $query->insertTag("last");
      $query->insertTag("nick");
      $query->insertTag("email");
 
      $query->insertTag("instructions")->data("juday is here to help.");
 
      # Send back to client
      $c->send($node);
  }

As you can see, here we're turning the incoming tag back around,
rather than creating a new one with the NodeFactory. Note that 
we don't have to worry about the id attribute anymore, nor call
insertTag(), but we do expect the incoming request to be 'clean',
i.e. not to contain any child elements in the <query/>. As I said,
it's just another way of looking at doing things ...

Anyway, that's a bit of a long answer, but there you go ;-)

cheers
dj



More information about the JDev mailing list