ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Net-XMPP2/lib/Net/XMPP2/Connection.pm
Revision: 1.14
Committed: Tue Apr 24 18:11:09 2007 UTC (19 years, 5 months ago) by elmex
Branch: MAIN
Changes since 1.13: +0 -14 lines
Log Message:
removed extension mechanisms which don't seem neccessary
to me anymore. noone wants XMPP without the XEPs (at least not me).

File Contents

# User Rev Content
1 elmex 1.1 package Net::XMPP2::Connection;
2     use strict;
3     use AnyEvent;
4     use IO::Socket::INET;
5     use Net::XMPP2::Parser;
6     use Net::XMPP2::Writer;
7 elmex 1.10 use Net::XMPP2::Util qw/split_jid/;
8 elmex 1.9 use Net::XMPP2::Event;
9     use Net::XMPP2::SimpleConnection;
10 elmex 1.1 use Net::XMPP2::Namespaces qw/xmpp_ns/;
11 elmex 1.10 use Net::XMPP2::Error;
12 elmex 1.1 use Net::DNS;
13 elmex 1.2
14 elmex 1.9 our @ISA = qw/Net::XMPP2::SimpleConnection Net::XMPP2::Event/;
15 elmex 1.1
16     =head1 NAME
17    
18     Net::XMPP2::Connection - A XML stream that implements the XMPP RFC 3920.
19    
20     =head1 SYNOPSIS
21    
22     use Net::XMPP2::Connection;
23    
24     my $con =
25     Net::XMPP2::Connection->new (
26     username => "abc",
27     domain => "jabber.org",
28     resource => "Net::XMPP2"
29     );
30    
31     $con->connect or die "Couldn't connect to jabber.org: $!";
32     $con->init;
33     $con->reg_cb (stream_ready => sub { print "XMPP stream ready!\n" });
34    
35     =head1 DESCRIPTION
36    
37     This module represents a XMPP stream as described in RFC 3920. You can issue the basic
38     XMPP XML stanzas with methods like C<send_iq>, C<send_message> and C<send_presence>.
39    
40     And receive events with the C<reg_cb> event framework from the connection.
41    
42     If you need instant messaging stuff please take a look at C<Net::XMPP2::IM::Connection>.
43    
44     =head1 METHODS
45    
46     =head2 new (%args)
47    
48     Following arguments can be passed in C<%args>:
49    
50     =over 4
51    
52     =item language => $tag
53    
54     This should be the language of the human readable contents that
55     will be transmitted over the stream. The default will be 'en'.
56    
57     Please look in RFC 3066 how C<$tag> should look like.
58    
59 elmex 1.10 =item jid => $jid
60    
61     This can be used to set the settings C<username>, C<domain>
62     (and optionally C<resource>) from a C<$jid>.
63    
64 elmex 1.13 =item register => $mode
65 elmex 1.12
66 elmex 1.13 If this settings is given this connection will attempt to register
67     an account in band on the server if C<$mode> is 'auto'.
68    
69     If C<$mode> is 'manual' the event C<in_band_register_form> will be
70     emitted (see also EVENTS documentation about the arguments of that
71     event, and how to continue the login procedure).
72 elmex 1.12
73 elmex 1.1 =item resource => $resource
74    
75     If this argument is given C<$resource> will be passed as desired
76     resource on resource binding.
77    
78     Note: You have to take care that the stringprep profile for
79     resources can be applied at: C<$resource>. Otherwise the server
80     might signal an error. See L<Net::XMPP2::Util> for utility functions
81     to check this.
82    
83     =item domain => $domain
84    
85     This is the destination host we are going to connect to.
86     As the connection won't be automatically connected use C<connect>
87     to initiate the connect.
88    
89     Note: A SRV RR lookup will be performed to discover the real hostname
90     and port to connect to. See also C<connect>.
91    
92 elmex 1.9 =item override_host => $host
93     =item override_port => $port
94    
95     This will be used as override to connect to.
96    
97 elmex 1.1 =item port => $port
98    
99     This is optional, the default port is 5222.
100    
101     Note: A SRV RR lookup will be performed to discover the real hostname
102     and port to connect to. See also C<connect>.
103    
104     =item username => $username
105    
106     This is your C<$username> (the userpart in the JID);
107    
108     Note: You have to take care that the stringprep profile for
109     nodes can be applied at: C<$username>. Otherwise the server
110     might signal an error. See L<Net::XMPP2::Util> for utility functions
111     to check this.
112    
113     =item password => $password
114    
115     This is the password for the C<username> above.
116    
117 elmex 1.5 =item disable_ssl => $bool
118    
119     If C<$bool> is true no SSL will be used.
120    
121 elmex 1.1 =back
122    
123     =cut
124    
125     sub new {
126     my $this = shift;
127     my $class = ref($this) || $this;
128     my $self = { language => 'en', @_ };
129     bless $self, $class;
130    
131     $self->{parser} = new Net::XMPP2::Parser;
132     $self->{writer} = Net::XMPP2::Writer->new (
133     write_cb => sub { $self->write_data ($_[0]) }
134     );
135    
136     $self->{parser}->set_stanza_cb (sub {
137     $self->handle_stanza (@_);
138     });
139    
140     $self->{iq_id} = 1;
141    
142     $self->{disconnect_cb} = sub {
143     my ($host, $port, $message) = @_;
144 elmex 1.7 delete $self->{authenticated};
145     delete $self->{ssl_enabled};
146 elmex 1.1 $self->event (disconnect => $host, $port, $message);
147     };
148    
149 elmex 1.10 if ($self->{jid}) {
150     my ($user, $host, $res) = split_jid ($self->{jid});
151     $self->{username} = $user;
152     $self->{domain} = $host;
153     $self->{resource} = $res if defined $res;
154     }
155    
156 elmex 1.7 for (qw/username password domain/) {
157     die "No '$_' argument given to new, but '$_' is required\n"
158     unless $self->{$_};
159     }
160    
161 elmex 1.1 return $self;
162     }
163    
164     =head2 connect ($no_srv_rr)
165    
166     Try to connect to the domain and port passed in C<new>.
167    
168     A SRV RR lookup will be performed on the domain to discover
169     the host and port to use. If you don't want this set C<$no_srv_rr>
170     to a true value. C<$no_srv_rr> is false by default.
171    
172     As the SRV RR lookup might return multiple host and you fail to
173     connect to one you might just call this function again to try a
174     different host.
175    
176     If C<connect> was successful and we connected a true value is returned.
177     If the connect was unsuccessful undef is returned and C<$!> will be set
178     to the error that occured while connecting.
179    
180     If you want to know whether further connection attempts might be more
181     successful (as SRV RR lookup may return multiple hosts) call C<may_try_connect>
182     (see also C<may_try_connect>).
183    
184     Note that an internal list will be kept of tried hosts. Use
185     C<reset_connect_tries> to reset the internal list of tried hosts.
186    
187     =cut
188    
189     sub connect {
190     my ($self, $no_srv_rr) = @_;
191    
192     my ($host, $port) = ($self->{domain}, $self->{port} || 5222);
193 elmex 1.9 if ($self->{override_host}) {
194     ($host, $port) = ($self->{override_host}, $self->{override_port} || 5222);
195 elmex 1.1
196 elmex 1.9 } else {
197     unless ($no_srv_rr) {
198     my $res = Net::DNS::Resolver->new;
199     my $p = $res->query ('_xmpp-client._tcp.'.$host, 'SRV');
200     if ($p) {
201     my @srvs = grep { $_->type eq 'SRV' } $p->answer;
202     if (@srvs) {
203     @srvs = sort { $a->priority <=> $b->priority } @srvs;
204     @srvs = sort { $b->weight <=> $a->weight } @srvs; # TODO
205     $port = $srvs[0]->port;
206     $host = $srvs[0]->target;
207     }
208 elmex 1.1 }
209     }
210     }
211    
212     if ($self->SUPER::connect ($host, $port)) {
213     $self->event (connect => $host, $port);
214     return 1;
215     } else {
216     return undef;
217     }
218     }
219    
220     =head2 may_try_connect
221    
222     Returns the number of left alternatives of hosts to connect to for the
223     domain passed to C<new>.
224    
225     An internal list of tried hosts will be managed by C<connect> and those
226     hosts will be ignored by a SRV RR lookup (which will be done if you
227     call this function).
228    
229     Use C<reset_connect_tries> to reset the internal list of tried hosts.
230    
231     =cut
232    
233     sub may_try_connect {
234     # TODO
235     }
236    
237     =head2 reset_connect_tries
238    
239     This function resets the internal list of tried hosts for C<connect>.
240     See also C<connect>.
241    
242     =cut
243    
244     sub reset_connect_tries {
245     # TODO
246     }
247    
248     sub handle_data {
249     my ($self, $buf) = @_;
250     $self->event (debug_recv => $$buf);
251     $self->{parser}->feed (substr $$buf, 0, (length $$buf), '');
252     }
253    
254 elmex 1.5 sub debug_wrote_data {
255     my ($self, $data) = @_;
256     $self->event (debug_send => $data);
257     }
258    
259 elmex 1.1 sub write_data {
260     my ($self, $data) = @_;
261     $self->SUPER::write_data ($data);
262     }
263    
264     sub handle_stanza {
265     my ($self, $p, $node) = @_;
266    
267     if ($node->eq (stream => 'features')) {
268     $self->event (stream_features => $node);
269     $self->handle_stream_features ($node);
270 elmex 1.4 $self->{features} = $node;
271 elmex 1.5
272 elmex 1.2 } elsif ($node->eq (tls => 'proceed')) {
273     $self->enable_ssl;
274     $self->{parser}->init;
275     $self->{writer}->init;
276     $self->{writer}->send_init_stream ($self->{language}, $self->{domain});
277    
278 elmex 1.11 } elsif ($node->eq (tls => 'failure')) {
279     $self->event ('tls_error');
280     $self->disconnect ('TLS failure on TLS negotiation.');
281    
282 elmex 1.1 } elsif ($node->eq (sasl => 'challenge')) {
283     $self->handle_sasl_challenge ($node);
284 elmex 1.11
285 elmex 1.1 } elsif ($node->eq (sasl => 'success')) {
286     $self->handle_sasl_success ($node);
287 elmex 1.11
288     } elsif ($node->eq (sasl => 'failure')) {
289     my $error = Net::XMPP2::Error::SASL->new (node => $node);
290     $self->event (sasl_error => $error);
291    
292 elmex 1.1 } elsif ($node->eq (client => 'iq')) {
293     $self->handle_iq ($node);
294 elmex 1.11
295 elmex 1.4 } elsif ($node->eq (client => 'message')) {
296 elmex 1.6 $self->event (message_xml => $node);
297 elmex 1.11
298 elmex 1.4 } elsif ($node->eq (client => 'presence')) {
299 elmex 1.6 $self->event (presence_xml => $node);
300 elmex 1.11
301 elmex 1.1 } elsif ($node->eq (stream => 'error')) {
302     $self->handle_error ($node);
303 elmex 1.11
304 elmex 1.1 } else {
305     warn "Didn't understood stanza: '" . $node->name . "'";
306     }
307     }
308    
309 elmex 1.10 =head2 init ()
310 elmex 1.1
311     Initiate the XML stream.
312    
313     =cut
314    
315     sub init {
316     my ($self) = @_;
317     $self->{writer}->send_init_stream ($self->{language}, $self->{domain});
318     }
319    
320 elmex 1.10 =head2 is_connected ()
321    
322     Returns true if the connection is still connected and stanzas can be
323     sent.
324    
325     =cut
326    
327     sub is_connected {
328     my ($self) = @_;
329     $self->{authenticated}
330     }
331    
332 elmex 1.1 =head2 send_iq ($type, $create_cb, $result_cb, %attrs)
333    
334     This method sends an IQ XMPP request.
335    
336     Please take a look at the documentation for C<send_iq> in Net::XMPP2::Writer
337     about the meaning of C<$type>, C<$create_cb> and C<%attrs>.
338    
339 elmex 1.4 C<$result_cb> will be called when a result was received. The first argument to
340     C<$result_cb> will be a Net::XMPP2::Node instance containing the IQ result
341     stanza contents.
342 elmex 1.1
343     If the IQ resulted in a stanza error the second argument to C<$result_cb> will
344     be C<undef> (if the error type was not 'continue') and the third argument will
345 elmex 1.10 be a L<Net::XMPP2::Error::IQ> object.
346 elmex 1.1
347 elmex 1.4 This method returns the newly generated id for this iq request.
348    
349 elmex 1.1 =cut
350    
351     sub send_iq {
352     my ($self, $type, $create_cb, $result_cb, %attrs) = @_;
353     my $id = $self->{iq_id}++;
354     $self->{iqs}->{$id} = $result_cb;
355     $self->{writer}->send_iq ($id, $type, $create_cb, %attrs);
356 elmex 1.4 $id
357     }
358    
359     =head2 reply_iq_result ($req_iq_node, $create_cb, %attrs)
360    
361     This method will generate a result reply to the iq request C<Net::XMPP2::Node>
362     in C<$req_iq_node>.
363    
364     Please take a look at the documentation for C<send_iq> in Net::XMPP2::Writer
365     about the meaning C<$create_cb> and C<%attrs>.
366    
367 elmex 1.6 Use C<$create_cb> to create the XML for the result.
368    
369 elmex 1.4 The type for this iq reply is 'result'.
370    
371     =cut
372    
373     sub reply_iq_result {
374     my ($self, $iqnode, $create_cb, %attrs) = @_;
375     $self->{writer}->send_iq ($iqnode->attr ('id'), 'result', $create_cb, %attrs);
376     }
377    
378     =head2 reply_iq_error ($req_iq_node, $error_type, $error, %attrs)
379    
380     This method will generate an error reply to the iq request C<Net::XMPP2::Node>
381     in C<$req_iq_node>.
382    
383     C<$error_type> is one of 'cancel', 'continue', 'modify', 'auth' and 'wait'.
384     C<$error> is one of the defined error conditions described in
385     L<Net::XMPP2::Writer::write_error_tag>.
386    
387     Please take a look at the documentation for C<send_iq> in Net::XMPP2::Writer
388 elmex 1.6 about the meaning of C<%attrs>.
389 elmex 1.4
390     The type for this iq reply is 'error'.
391    
392     =cut
393    
394     sub reply_iq_error {
395     my ($self, $iqnode, $errtype, $error, %attrs) = @_;
396    
397     $self->{writer}->send_iq (
398     $iqnode->attr ('id'), 'error',
399     sub { $self->{writer}->write_error_tag ($iqnode, $errtype, $error) },
400     %attrs
401     );
402 elmex 1.1 }
403    
404     sub handle_iq {
405     my ($self, $node) = @_;
406    
407 elmex 1.4 my $type = $node->attr ('type');
408    
409     if ($type eq 'result') {
410     if (my $cb = delete $self->{iqs}->{$node->attr ('id')}) {
411 elmex 1.1 $cb->($node);
412     }
413 elmex 1.9
414 elmex 1.4 } elsif ($type eq 'error') {
415     if (my $cb = delete $self->{iqs}->{$node->attr ('id')}) {
416 elmex 1.1
417 elmex 1.10 my $error = Net::XMPP2::Error::IQ->new (node => $node);
418     $cb->(($error->type eq 'continue' ? $node : undef), $error);
419 elmex 1.1 }
420 elmex 1.4
421     } else {
422     my $handled = 0;
423 elmex 1.6 $self->event ("iq_${type}_request_xml" => $node, \$handled);
424 elmex 1.4
425     my @from;
426     push @from, (to => $node->attr ('from')) if $node->attr ('from');
427    
428     unless ($handled) {
429 elmex 1.5 $self->reply_iq_error ($node, undef, 'feature-not-implemented', @from);
430 elmex 1.4 }
431 elmex 1.1 }
432     }
433    
434 elmex 1.12 sub send_sasl_auth {
435     my ($self, @mechs) = @_;
436     $self->{writer}->send_sasl_auth (
437     (join ' ', map { $_->text } @mechs),
438     $self->{username}, $self->{domain}, $self->{password}
439     );
440     }
441    
442 elmex 1.13 =head2 request_inband_register_form ($finish_cb)
443    
444     This method starts a in-band-registration attempt. When finished C<$finish_cb>
445     will be called with the first argument being a L<Net::XMPP2::RegisterForm>
446     object (will be undef if an error occured) and the second an optional error
447     object of type L<Net::XMPP2::Error::Register> if an error occured.
448    
449     =cut
450    
451     sub request_inband_register_form {
452     my ($self, $finish_cb) = @_;
453    
454     $self->send_iq (
455     get =>
456     sub {
457     my ($w) = @_;
458     $w->addPrefix (xmpp_ns ('register'), '');
459     $w->emptyTag ([qw/register query/]);
460     },
461     sub {
462     my ($node, $error) = @_;
463     my $form;
464     $form = Net::XMPP2::RegisterForm (node => $node, connection => $self)
465     unless $error;
466     $finish_cb->($form, $error);
467     }
468     );
469     }
470    
471     sub do_auto_register {
472     my ($self, $mechs) = @_;
473    
474     $self->request_inband_register_form (sub {
475     my ($form, $error) = @_;
476    
477     if ($error) {
478     $self->event (in_band_register_error => $error);
479    
480     } else {
481     if ($self->{register} ne 'manual') {
482     # of course this blows up if the form was more complicated
483     # any ideas?
484     $form->auto_submit (
485     username => $self->{username},
486     password => $self->{password},
487     cb => sub {
488     my ($form, $error) = @_;
489     if ($error) {
490     $self->event (auto_in_band_register_error => $error);
491     } else {
492     $self->event ('auto_in_band_register_ok');
493     $self->send_sasl_auth (@$mechs) if @$mechs;
494     }
495     }
496     );
497    
498     } else {
499     $self->event (
500     in_band_register_form =>
501     $form,
502     sub { $self->send_sasl_auth (@$mechs) if @$mechs }
503     )
504     }
505     }
506     });
507    
508     }
509    
510 elmex 1.1 sub handle_stream_features {
511     my ($self, $node) = @_;
512     my @mechs = $node->find_all ([qw/sasl mechanisms/], [qw/sasl mechanism/]);
513     my @bind = $node->find_all ([qw/bind bind/]);
514 elmex 1.2 my @tls = $node->find_all ([qw/tls starttls/]);
515 elmex 1.13
516     # and yet another weird thingie: in XEP-0077 it's said that
517     # the register feature MAY be advertised by the server. That means:
518     # it MAY not be advertised even if it is available... so we don't
519     # care about it...
520     # my @reg = $node->find_all ([qw/register register/]);
521 elmex 1.1
522 elmex 1.5 if (not ($self->{disable_ssl}) && not ($self->{ssl_enabled}) && @tls) {
523 elmex 1.2 $self->{writer}->send_starttls;
524    
525 elmex 1.12 } elsif (not $self->{authenticated}) {
526 elmex 1.13 if ($self->{register}) {
527     $self->do_auto_register (\@mechs);
528 elmex 1.12 } else {
529     $self->send_sasl_auth (@mechs) if @mechs;
530     }
531 elmex 1.1
532     } elsif (@bind) {
533     $self->do_rebind ($self->{resource});
534     }
535     }
536    
537     sub handle_sasl_challenge {
538     my ($self, $node) = @_;
539     $self->{writer}->send_sasl_response ($node->text);
540     }
541    
542     sub handle_sasl_success {
543     my ($self, $node) = @_;
544     $self->{authenticated} = 1;
545     $self->{parser}->init;
546     $self->{writer}->init;
547     $self->{writer}->send_init_stream ($self->{language}, $self->{domain});
548     }
549    
550     sub handle_error {
551     my ($self, $node) = @_;
552 elmex 1.10 my $error = Net::XMPP2::Error::Stream->new (node => $node);
553    
554     $self->event (stream_error => $error);
555 elmex 1.1 $self->{writer}->send_end_of_stream;
556     }
557    
558 elmex 1.4 =head2 send_presence ($type, $create_cb, %attrs)
559    
560     This method sends a presence stanza, for the meanings
561     of C<$type>, C<$create_cb> and C<%attrs> please take a look
562     at the documentation for L<Net::XMPP2::Writer::send_presence>.
563    
564     This methods does attach an id attribute to the message stanza and
565     will return the id that was used (so you can react on possible replies).
566    
567     =cut
568    
569     sub send_presence {
570     my ($self, $type, $create_cb, %attrs) = @_;
571     my $id = $self->{iq_id}++;
572     $self->{writer}->send_presence ($id, $type, $create_cb, %attrs);
573     $id
574     }
575    
576     =head2 send_message ($to, $type, $create_cb, %attrs)
577    
578     This method sends a presence stanza, for the meanings
579     of C<$to>, C<$type>, C<$create_cb> and C<%attrs> please take a look
580     at the documentation for L<Net::XMPP2::Writer::send_message>.
581    
582     This methods does attach an id attribute to the message stanza and
583     will return the id that was used (so you can react on possible replies).
584    
585     =cut
586    
587     sub send_message {
588     my ($self, $to, $type, $create_cb, %attrs) = @_;
589     my $id = $self->{iq_id}++;
590     $self->{writer}->send_message ($id, $to, $type, $create_cb, %attrs);
591     $id
592     }
593    
594 elmex 1.1 =head2 do_rebind ($resource)
595    
596     In case you got a C<bind_error> event and want to retry
597     binding you can call this function to set a new C<$resource>
598     and retry binding.
599    
600     If it fails again you can call this again. Becareful not to
601     end up in a loop!
602    
603     If binding was successful the C<stream_ready> event will be generated.
604    
605     =cut
606    
607     sub do_rebind {
608     my ($self, $resource) = @_;
609     $self->{resource} = $resource;
610     $self->send_iq (
611     set =>
612     sub {
613     my ($w) = @_;
614     if ($self->{resource}) {
615     $w->startTag ([xmpp_ns ('bind'), 'bind']);
616     $w->startTag ([xmpp_ns ('bind'), 'resource']);
617     $w->characters ($self->{resource});
618     $w->endTag;
619     $w->endTag;
620     } else {
621     $w->emptyTag ([xmpp_ns ('bind'), 'bind'])
622     }
623     },
624     sub {
625 elmex 1.13 my ($ret_iq, $error) = @_;
626 elmex 1.1
627 elmex 1.13 if ($error) {
628 elmex 1.10 my ($res) = $error->xml_node ()->find_all ([qw/bind bind/], [qw/bind resource/]);
629     $self->event (bind_error => $error, ($res ? $res : $self->{resource}));
630 elmex 1.1
631     } else {
632     my @jid = $ret_iq->find_all ([qw/bind bind/], [qw/bind jid/]);
633     my $jid = $jid[0]->text;
634     unless ($jid) { die "Got empty JID tag from server!\n" }
635     $self->{jid} = $jid;
636    
637     $self->event (stream_ready => $jid);
638     }
639     }
640     );
641     }
642    
643     =head2 jid
644    
645     After the stream has been bound to a resource the JID can be retrieved via this
646     method.
647    
648     =cut
649    
650     sub jid { $_[0]->{jid} }
651    
652 elmex 1.4 =head2 features
653    
654     Returns the last received <features> tag in form of an L<Net::XMPP2::Node> object.
655    
656     =cut
657    
658     sub features { $_[0]->{features} }
659    
660 elmex 1.1 =head1 EVENTS
661    
662     These events can be registered on with C<reg_cb>:
663    
664     =over 4
665    
666 elmex 1.11 =item stream_features => $node
667 elmex 1.1
668 elmex 1.4 This event is sent when a stream feature (<features>) tag is received. C<$node> is the
669     L<Net::XMPP2::Node> object that represents the <features> tag.
670 elmex 1.1
671     =item stream_ready => $jid
672    
673     This event is sent if the XML stream has been established (and
674     resources have been bound) and is ready for transmitting regular stanzas.
675    
676     C<$jid> is the bound jabber id.
677    
678 elmex 1.10 =item stream_error => $error
679 elmex 1.6
680     This event is sent if a XML stream error occured. C<$error>
681 elmex 1.10 is a L<Net::XMPP2::Error::Stream> object.
682 elmex 1.6
683 elmex 1.11 =item tls_error
684    
685     This event is emitted when a TLS error occured on TLS negotiation.
686     After this the connection will be disconnected.
687    
688     =item sasl_error => $error
689    
690     This event is emitted on SASL authentication error.
691    
692 elmex 1.10 =item bind_error => $error, $resource
693 elmex 1.6
694 elmex 1.10 This event is generated when the stream was unable to bind to
695     any or the in C<new> specified resource. C<$error> is a L<Net::XMPP2::Error::IQ>
696     object. C<$resource> is the errornous resource string or undef if none
697     was received.
698 elmex 1.6
699 elmex 1.10 The C<condition> of the C<$error> might be one of: 'bad-request',
700     'not-allowed' or 'conflict'.
701 elmex 1.1
702     Node: this is untested, i couldn't get the server to send a bind error
703     to test this.
704    
705     =item connect => $host, $port
706    
707     This event is generated when a successful connect was performed to
708     the domain passed to C<new>.
709    
710     Note: C<$host> and C<$port> might be different from the domain you passed to
711     C<new> if C<connect> performed a SRV RR lookup.
712    
713     If this connection is lost a C<disconnect> will be generated with the same
714     C<$host> and C<$port>.
715    
716     =item disconnect => $host, $port, $message
717    
718     This event is generated when the connection was lost or another error
719     occured while writing or reading from it.
720    
721     C<$message> is a humand readable error message for the failure.
722     C<$host> and C<$port> were the host and port we were connected to.
723    
724     Note: C<$host> and C<$port> might be different from the domain you passed to
725     C<new> if C<connect> performed a SRV RR lookup.
726    
727 elmex 1.6 =item presence_xml => $node
728 elmex 1.4
729     This event is sent when a presence stanza is received. C<$node> is the
730     L<Net::XMPP2::Node> object that represents the <presence> tag.
731    
732 elmex 1.6 =item message_xml => $node
733 elmex 1.4
734     This event is sent when a message stanza is received. C<$node> is the
735     L<Net::XMPP2::Node> object that represents the <message> tag.
736    
737 elmex 1.6 =item iq_set_request_xml => $node, $handled_ref
738 elmex 1.4
739 elmex 1.6 =item iq_get_request_xml => $node, $handled_ref
740 elmex 1.4
741     These events are sent when an iq request stanza of type 'get' or 'set' is received.
742     C<$type> will either be 'get' or 'set' and C<$node> will be the L<Net::XMPP2::Node>
743     object of the iq tag.
744    
745     If C<$$handled_ref> is true an event handler should not handle this message anymore.
746    
747     If one of the event handlers handled this message the scalar pointed at by
748     the reference in C<$handled_ref> should be set to 1 true value. If C<$$handled_ref>
749     is still false after all event handlers were executed an error iq will be generated.
750    
751 elmex 1.1 =back
752    
753     =head1 AUTHOR
754    
755     Robin Redeker, C<< <elmex at ta-sa.org> >>
756    
757     =head1 COPYRIGHT & LICENSE
758    
759     Copyright 2007 Robin Redeker, all rights reserved.
760    
761     This program is free software; you can redistribute it and/or modify it
762     under the same terms as Perl itself.
763    
764     =cut
765    
766     1; # End of Net::XMPP2