Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

Net::XMPP module:Check for chat messages on server

by gauss76 (Scribe)
on May 10, 2019 at 08:05 UTC ( [id://1233550]=perlquestion: print w/replies, xml ) Need Help??

gauss76 has asked for the wisdom of the Perl Monks concerning the following question:

Hi All,

I am currently experimenting with the perl module Net::XMPP to try and connect to a chat server and be notified of new chat messages. I have taken the following client.pl code from the examples page of the Net:XMPP Perl site.

use Net::XMPP; use strict; if ($#ARGV < 4) { print "\nperl client.pl <server> <port> <username> <password> <res +ource> \n\n"; exit(0); } my $server = $ARGV[0]; my $port = $ARGV[1]; my $username = $ARGV[2]; my $password = $ARGV[3]; my $resource = $ARGV[4]; $SIG{HUP} = \&Stop; $SIG{KILL} = \&Stop; $SIG{TERM} = \&Stop; $SIG{INT} = \&Stop; my $Connection = new Net::XMPP::Client(); $Connection->SetCallBacks(message=>\&InMessage, presence=>\&InPresence, iq=>\&InIQ); my $status = $Connection->Connect(hostname=>$server, port=>$port); if (!(defined($status))) { print "ERROR: Jabber server is down or connection was not allowed +.\n"; print " ($!)\n"; exit(0); } my @result = $Connection->AuthSend(username=>$username, password=>$password, resource=>$resource); if ($result[0] ne "ok") { print "ERROR: Authorization failed: $result[0] - $result[1]\n"; exit(0); } print "Logged in to $server:$port...\n"; $Connection->RosterGet(); print "Getting Roster to tell server to send presence info...\n"; $Connection->PresenceSend(); print "Sending presence to tell world that we are logged in...\n"; while(defined($Connection->Process())) { } print "ERROR: The connection was killed...\n"; exit(0); sub Stop { print "Exiting...\n"; $Connection->Disconnect(); exit(0); } sub InMessage { my $sid = shift; my $message = shift; my $type = $message->GetType(); my $fromJID = $message->GetFrom("jid"); my $from = $fromJID->GetUserID(); my $resource = $fromJID->GetResource(); my $subject = $message->GetSubject(); my $body = $message->GetBody(); print "===\n"; print "Message ($type)\n"; print " From: $from ($resource)\n"; print " Subject: $subject\n"; print " Body: $body\n"; print "===\n"; print $message->GetXML(),"\n"; print "===\n"; } sub InIQ { my $sid = shift; my $iq = shift; my $from = $iq->GetFrom(); my $type = $iq->GetType(); my $query = $iq->GetQuery(); my $xmlns = $query->GetXMLNS(); print "===\n"; print "IQ\n"; print " From $from\n"; print " Type: $type\n"; print " XMLNS: $xmlns"; print "===\n"; print $iq->GetXML(),"\n"; print "===\n"; } sub InPresence { my $sid = shift; my $presence = shift; my $from = $presence->GetFrom(); my $type = $presence->GetType(); my $status = $presence->GetStatus(); print "===\n"; print "Presence\n"; print " From $from\n"; print " Type: $type\n"; print " Status: $status\n"; print "===\n"; print $presence->GetXML(),"\n"; print "===\n"; }
It all works correctly until the line
while(defined($Connection->Process())) { }

where I get the following error:

"There was an error in the last call to Process that you did not check for and handle. You should always check the output of the Process call. If it was undef then there was a fatal error that you need to check. There is an error in your program at client.pl line x"

So, my question, how do I check the output of the process call? I have tried to assign it to a variable and also check if it is defined but anything I seem to do results in the same error message above.

Replies are listed 'Best First'.
Re: Net::XMPP module:Check for chat messages on server
by thanos1983 (Parson) on May 10, 2019 at 15:16 UTC

    Hello gauss76,

    There is a similar question Issues connecting to openfire via Net::XMPP.

    There is a proposed solution can you check if it is working for you?

    Hope this helps, BR.

    Seeking for Perl wisdom...on the process of learning...not there...yet!

      Thanks for the info...I applied the proposed patch and now I get the following fatal SSL error

      XML::Stream: new: hostname = (xxx) XML::Stream: SetCallBacks: tag(node) func(CODE(0x37f1608)) XMPP::Conn: xmppCallbackInit: start XMPP::Conn: SetCallBacks: tag(message) func(CODE(0x37f1860)) XMPP::Conn: SetCallBacks: tag(presence) func(CODE(0x37f17a0)) XMPP::Conn: SetCallBacks: tag(iq) func(CODE(0x37f1680)) XMPP::Conn: SetPresenceCallBacks: type(subscribe) func(CODE(0x37f1788) +) XMPP::Conn: SetPresenceCallBacks: type(subscribed) func(CODE(0x37f1ae8 +)) XMPP::Conn: SetPresenceCallBacks: type(unsubscribe) func(CODE(0x37f1a2 +8)) XMPP::Conn: SetPresenceCallBacks: type(unsubscribed) func(CODE(0x37f1b +a8)) XMPP::Conn: SetDirectXPathCallBacks: xpath(/[@xmlns="urn:ietf:params:x +ml:ns:xmpp-tls"]) func(CODE(0x37f1ad0)) XMPP::Conn: SetDirectXPathCallBacks: xpath(/[@xmlns="urn:ietf:params:x +ml:ns:xmpp-sasl"]) func(CODE(0x37f1cb0)) XMPP::Conn: xmppCallbackInit: stop XMPP::Conn: SetCallBacks: tag(iq) func(CODE(0x37efb88)) XMPP::Conn: SetCallBacks: tag(presence) func(CODE(0x37eff90)) XMPP::Conn: SetCallBacks: tag(message) func(CODE(0x37ef6c0)) XMPP::Conn: Connect: host(hostpart:5222) namespace(jabber:client) XMPP::Conn: Connect: timeout(10) XML::Stream: Connect: type(tcpip) XML::Stream: Connect: Got a connection XML::Stream: Send: (<?xml version='1.0'?><stream:stream version='1.0' +xmlns:stream='http://etherx.jabber.org/streams' xmlns='jabber:client' + to='hostpart' from='xxx' xml:lang='en' >) XML::Stream: Read: buff(<?xml version='1.0' encoding='utf-8'?><stream: +stream xmlns:stream="http://etherx.jabber.org/streams" from="hostpart +" id="078414e9-d180-43c3-bab9-6ea07a1ae870" version="1.0" xmlns="jabb +er:client">) XML::Stream: Read: buff(<stream:features xmlns:stream="http://etherx.j +abber.org/streams"><starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls"/ +></stream:features>) XMPP::Conn: Connect: connection made XML::Stream: SetCallBacks: tag(node) func(CODE(0x37f1728)) XML::Stream: Send: (<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/ +>) XML::Stream: Read: buff(<proceed xmlns="urn:ietf:params:xml:ns:xmpp-tl +s"/>) XML::Stream: TLSClientProceed: Convert normal socket to SSL XML::Stream: TLSClientProceed: sock(IO::Socket::INET=GLOB(0x37f1e00)) XML::Stream: LoadSSL: Load the IO::Socket::SSL module XML::Stream: LoadSSL: Success XML::Stream: TLSClientProceed: Error during start_SSL: SSL connect att +empt failed with unknown error error:14090086:SSL routines:SSL3_GET_S +ERVER_CERTIFICATE:certificate verify failed

      So, is there any way to resolve this SSL error?

      I have a certificate file that I point to with the command below (certificate was taken from the directory of a Windows Pidgin client install that connects to the server with no problems. (Please note that the code I am running is on a windows machine running strawberry Perl))

      my $path='C:\Program Files (x86)\Pidgin\ca-certs'; my $status = $Connection->Connect(hostname=>$server, port=>$port, connectiontype => 'tcpip', tls => 1, ssl_ca_path =>$path);

      Where all the variables are declared beforehand

      However I have noticed that if I change the folder in the $path variable to another location that exists on my windows system I get the same SSL error so is there a fundamental problem with my Pidgin certificate?

      Any further help much appreciated as have now been looking at this for a while with zero progress!

Re: Net::XMPP module:Check for chat messages on server
by gauss76 (Scribe) on May 10, 2019 at 10:11 UTC

    I now have some more information.

    Replacing

    my $Connection = new Net::XMPP::Client();

    with

    my $Connection = new Net::XMPP::Client(debuglevel=>1);

    Gives debugging output. From this I can see that the problem is actually with the line

    $Connection->RosterGet();

    which gives the following output

    XMPP::Conn: SendAndReceiveWithID: object(Net::XMPP::IQ=HASH(0x37eb8c8) +) XMPP::Conn: SendWithID: id(netjabber-2) XMPP::Conn: SendWithID: in(<iq type='get'><query xmlns='jabber:iq:rost +er'/></iq>) XMPP::Conn: RegisterID: tag(iq) id(netjabber-2) XMPP::Conn: SendWithID: out(<iq id='netjabber-2' type='get'><query xml +ns='jabber:iq:roster'/></iq>) XMPP::Conn: SendXML: sent(<iq id='netjabber-2' type='get'><query xmlns +='jabber:iq:roster'/></iq>) XML::Stream: Send: (<iq id='netjabber-2' type='get'><query xmlns='jabb +er:iq:roster'/></iq>) XMPP::Conn: SendAndReceiveWithID: sent with id(netjabber-2) XMPP::Conn: WaitForID: id(netjabber-2) XMPP::Conn: ReceivedID: id(netjabber-2) XMPP::Conn: ReceivedID: nope... XMPP::Conn: WaitForID: haven't gotten it yet... let's wait for more pa +ckets XMPP::Conn: Process: timeout(1) XML::Stream: Read: buff() XML::Stream: Read: ERROR Getting Roster to tell server to send presence info...

    It can be seen here that the "Process" timed out which gives the error in my original post...but how to fix?

      You can set the timeout to be as long as you like when you Connect and also when calling some of the other methods too. If the problem persists even with suitably long timeouts set then you may have a networking issue unrelated to Perl.

        Thanks, but connecting is no problem, that part works, and there seems to be no such option for the RosterGet part that I can see

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1233550]
Approved by hippo
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others musing on the Monastery: (4)
As of 2024-04-18 22:58 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found