views:

995

answers:

4

I'm trying to write a simple Perl script to send an Instant Message. Jabber seemed like it might be the most conducive protocol. But the following script fails:

#!/usr/bin/env perl
use Jabber::SimpleSend qw(send_jabber_message);
send_jabber_message('[email protected]',
                    'CENSORED',
                    '[email protected]',
                    'subject test',
                    "body test");

It says:

Can't call method "can_read" on an undefined value at 
/opt/local/lib/perl5/site_perl/5.8.9/XML/Stream.pm line 1421.

As cartman's answer points out, the code should actually be

#!/usr/bin/env perl
use Jabber::SimpleSend qw(send_jabber_message);
send_jabber_message('me%[email protected]',
                    'CENSORED',
                    'you%[email protected]',
                    'subject test',
                    "body test");

But that fails with the following error:

No SASL mechanism found
 at /usr/local/lib/perl5/site_perl/5.10.0/Authen/SASL.pm line 74

I do have the Authen::SASL cpan module installed.

+1  A: 

I'm not familiar with the code, but that line in XML::Stream is where the module begins a select() loop. Line 523-524 is where is passes IO::Select a socket to the destination server, and IO::Select itself passes a blessed reference, which should never be undef the way XML::Stream uses it.

Something is probably modifying the "SELECT" element of the XML::Stream object in the Jabber modules, possibly in a misguided attempt to correct a server connection error. I'm sorry I couldn't be more specific.


In response to the update:

These are odd errors, and I've been meaning to look inside the Jabber modules anyway, so I took at look at the source. The following is based on looking at the latest versions of the modules used available from CPAN. This is probably not very useful unless you want to start subclassing these modules and adding code to see where something unexpected happens. (You can skip the next paragraph if you're not interested in the Jabber modules' internals.)

From the updated information, I've traced it to the point where Authen::SASL::Perl croaks on line 41. It needs a result from $parent->mechanism, and there are two possible causes, assuming Authen::SASL isn't broken. Either it's being called incorrectly with no arguments from Net::XMPP::Protocol (line 2968), which seems unlikely, or the "mechanisms" it set in the constructor for Authen::SASL don't exist. Net::XMPP::Protocol defines the "mechanisms" (GetStreamFeature called, line 2958; that method defined around line 3340) with return $self->{STREAM}->GetStreamFeature($self->GetStreamID(),$feature);, where $feature is just a string passed from the callee and the id part of the XML::Stream object's session.

Based on the original XML error and the possibility of the session id going bad, it appears that the server either sends bad data at some point unexpected to XML::Stream and unaccounted for by the modules using it. I'm not convinced that foo%[email protected] is the right user name format, but I don't know how that could be causing these errors without the Jabber server doing something wrong.

I would start fresh with different user names on a different server and see if Jabber::SimpleSend works at all, then try to capture the server's output somehow to see what XML::Stream is choking on.


Update: For what it's worth, I installed the module and I'm getting the exact same errors. Authen::SASL::Perl::PLAIN and all other prerequisites do exist. And when I set the user name to [email protected] and enabled global warnings (eg, #!/usr/bin/perl -w or perl -w filename.pl), XML::Stream reveals a bunch of undefined value problems, and SimpleSend actually spits out the warning "Could not connect to Jabber server"! (No, I don't know what that really means :().


Update: I was trying to install Net::Jabber::Bot (I gave up after some ssl module errors) to see if it would solve anything, and I noticed its constructor has this option and note:

gtalk => 0 # Default to off, 1 for on. needed now due to gtalk differences from std jabber server.

which reinforces the idea that the server's doing something unusual, which XML::Stream doesn't bother to throw an exception for.

Anonymous
Wow, thanks for all this detective work! You wouldn't happen to have a test username/pw on some other jabber server for me to test with handy, would you?
dreeves
No, I don't; sorry. But I remember finding some servers that I once used with Pidgin that would automatically create the username for you if it didn't exist. I have no idea whether the Net::Jabber and Net::XMPP can handle that, but you could always create the accounts manually and then play with it in the module.
Anonymous
+1  A: 

Your username should be [email protected] but the server name is talk.google.com. So the first parameter should be [email protected]@talk.google.com, but I am not sure if Perl can grok that double @ signs. You may try to escape first @ with %40 so that the first parameter is me%[email protected] .

Update I: About the second error, looks like you are missing SASL authentication modules. GMail uses SASL Plain authentication. So do you have /usr/local/lib/perl5/site_perl/5.10.0/Authen/SASL/Perl/PLAIN.pm file ?

cartman
Thanks cartman! This is progress. Now it complains "No SASL mechanism found" (and I do have the cpan module Authen::SASL installed). I just updated the question to ask about the new error.
dreeves
Confirmed. I do have it.
dreeves
Try installing Authen::Cyrus::SASL module.
cartman
I installed Authen::SASL::Perl and then got the original error ('Can't call method "can_read"'). Installing Authen::SASL::Cyrus fails: "Failed during this command: ADAMSON/Authen-SASL-Cyrus-0.12.tar.gz : make_test NO"
dreeves
Posting full build log would be better.
cartman
+1  A: 

Looks like you require Authen::SASL::Cyrus (the C implementation) or Authen::SASL::Perl (the Perl implementation) to be installed as well as Authen::SASL (which simply tries to find the best option installed on your machine, and, for you, finds neither).

Check to see if you have one of them installed.

That's my reading of the source and the manual - I've not tested this, ymmv.

ijw
Nope; I did install and verify that module existed and that's not it.
Anonymous
Which one, Authen::SASL::Cyrus or Authen::SASL::Perl?
ijw
I have the pure-Perl Authen::SASL::Perl, and Authen::SASL::Perl::PLAIN which I think subclasses it, and not the Cyrus part. It's the standard install without a compiler configured in CPAN.
Anonymous
http://www.nntp.perl.org/group/perl.ldap/2006/08/msg2280.html (old but the reason is still possible) - try ::Cyrus ?
ijw
I installed Authen::SASL::Perl and then got the original error ('Can't call method "can_read"'). Installing Authen::SASL::Cyrus fails: "Failed during this command: ADAMSON/Authen-SASL-Cyrus-0.12.tar.gz : make_test NO"
dreeves
http://nolan.eakins.net/node/300 - Google SASL is special.http://www.pervasive-network.org/SPIP/Google-Talk-with-perl-bis - but there may be an alternative way, if you can use these settings with Jabber::SimpleClient.
ijw
+2  A: 

Jabber::SimpleSend is the easier way to interact with a standard Jabber server but don't let the module name mislead you: gtalk is indeed a bit different, requiring TLS encryption (that Jabber::SimpleSend won't do) and a hostname change. You will get better results using Net::XMPP and dealing directly with its API.

See http://www.gridpp.ac.uk/wiki/Nagios_jabber_notification for a well-commented, fully working implementation in 75 lines of perl using Net::XMPP. It's inteded to send nagios notifications but it does exactly what you need.

codehead