ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Net-XMPP2/lib/Net/XMPP2/Connection.pm
Revision: 1.18
Committed: Mon Jun 25 07:56:52 2007 UTC (19 years, 3 months ago) by elmex
Branch: MAIN
Changes since 1.17: +16 -3 lines
Log Message:
sime fixes and changes

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 elmex 1.15 $self->{iq_id} = 1;
141     $self->{default_iq_timeout} = 60;
142 elmex 1.1
143     $self->{disconnect_cb} = sub {
144     my ($host, $port, $message) = @_;
145 elmex 1.7 delete $self->{authenticated};
146     delete $self->{ssl_enabled};
147 elmex 1.1 $self->event (disconnect => $host, $port, $message);
148     };
149    
150 elmex 1.10 if ($self->{jid}) {
151     my ($user, $host, $res) = split_jid ($self->{jid});
152     $self->{username} = $user;
153     $self->{domain} = $host;
154     $self->{resource} = $res if defined $res;
155     }
156    
157 elmex 1.7 for (qw/username password domain/) {
158     die "No '$_' argument given to new, but '$_' is required\n"
159     unless $self->{$_};
160     }
161    
162 elmex 1.1 return $self;
163     }
164    
165     =head2 connect ($no_srv_rr)
166    
167     Try to connect to the domain and port passed in C<new>.
168    
169     A SRV RR lookup will be performed on the domain to discover
170     the host and port to use. If you don't want this set C<$no_srv_rr>
171     to a true value. C<$no_srv_rr> is false by default.
172    
173     As the SRV RR lookup might return multiple host and you fail to
174     connect to one you might just call this function again to try a
175     different host.
176    
177     If C<connect> was successful and we connected a true value is returned.
178     If the connect was unsuccessful undef is returned and C<$!> will be set
179     to the error that occured while connecting.
180    
181     If you want to know whether further connection attempts might be more
182     successful (as SRV RR lookup may return multiple hosts) call C<may_try_connect>
183     (see also C<may_try_connect>).
184    
185     Note that an internal list will be kept of tried hosts. Use
186     C<reset_connect_tries> to reset the internal list of tried hosts.
187    
188     =cut
189    
190     sub connect {
191     my ($self, $no_srv_rr) = @_;
192    
193     my ($host, $port) = ($self->{domain}, $self->{port} || 5222);
194 elmex 1.9 if ($self->{override_host}) {
195     ($host, $port) = ($self->{override_host}, $self->{override_port} || 5222);
196 elmex 1.1
197 elmex 1.9 } else {
198     unless ($no_srv_rr) {
199     my $res = Net::DNS::Resolver->new;
200     my $p = $res->query ('_xmpp-client._tcp.'.$host, 'SRV');
201     if ($p) {
202     my @srvs = grep { $_->type eq 'SRV' } $p->answer;
203     if (@srvs) {
204     @srvs = sort { $a->priority <=> $b->priority } @srvs;
205     @srvs = sort { $b->weight <=> $a->weight } @srvs; # TODO
206     $port = $srvs[0]->port;
207     $host = $srvs[0]->target;
208     }
209 elmex 1.1 }
210     }
211     }
212    
213     if ($self->SUPER::connect ($host, $port)) {
214     $self->event (connect => $host, $port);
215     return 1;
216     } else {
217     return undef;
218     }
219     }
220    
221     =head2 may_try_connect
222    
223     Returns the number of left alternatives of hosts to connect to for the
224     domain passed to C<new>.
225    
226     An internal list of tried hosts will be managed by C<connect> and those
227     hosts will be ignored by a SRV RR lookup (which will be done if you
228     call this function).
229    
230     Use C<reset_connect_tries> to reset the internal list of tried hosts.
231    
232     =cut
233    
234     sub may_try_connect {
235     # TODO
236     }
237    
238     =head2 reset_connect_tries
239    
240     This function resets the internal list of tried hosts for C<connect>.
241     See also C<connect>.
242    
243     =cut
244    
245     sub reset_connect_tries {
246     # TODO
247     }
248    
249     sub handle_data {
250     my ($self, $buf) = @_;
251     $self->event (debug_recv => $$buf);
252     $self->{parser}->feed (substr $$buf, 0, (length $$buf), '');
253     }
254    
255 elmex 1.5 sub debug_wrote_data {
256     my ($self, $data) = @_;
257     $self->event (debug_send => $data);
258     }
259    
260 elmex 1.1 sub write_data {
261     my ($self, $data) = @_;
262     $self->SUPER::write_data ($data);
263     }
264    
265     sub handle_stanza {
266     my ($self, $p, $node) = @_;
267    
268 elmex 1.18 if (not defined $node) { # got stream end
269     $self->disconnect ("end of 'XML' stream encountered");
270     return;
271     }
272    
273 elmex 1.1 if ($node->eq (stream => 'features')) {
274     $self->event (stream_features => $node);
275     $self->handle_stream_features ($node);
276 elmex 1.4 $self->{features} = $node;
277 elmex 1.5
278 elmex 1.2 } elsif ($node->eq (tls => 'proceed')) {
279     $self->enable_ssl;
280     $self->{parser}->init;
281     $self->{writer}->init;
282     $self->{writer}->send_init_stream ($self->{language}, $self->{domain});
283    
284 elmex 1.11 } elsif ($node->eq (tls => 'failure')) {
285     $self->event ('tls_error');
286     $self->disconnect ('TLS failure on TLS negotiation.');
287    
288 elmex 1.1 } elsif ($node->eq (sasl => 'challenge')) {
289     $self->handle_sasl_challenge ($node);
290 elmex 1.11
291 elmex 1.1 } elsif ($node->eq (sasl => 'success')) {
292     $self->handle_sasl_success ($node);
293 elmex 1.11
294     } elsif ($node->eq (sasl => 'failure')) {
295     my $error = Net::XMPP2::Error::SASL->new (node => $node);
296     $self->event (sasl_error => $error);
297    
298 elmex 1.1 } elsif ($node->eq (client => 'iq')) {
299     $self->handle_iq ($node);
300 elmex 1.11
301 elmex 1.4 } elsif ($node->eq (client => 'message')) {
302 elmex 1.6 $self->event (message_xml => $node);
303 elmex 1.11
304 elmex 1.4 } elsif ($node->eq (client => 'presence')) {
305 elmex 1.6 $self->event (presence_xml => $node);
306 elmex 1.11
307 elmex 1.1 } elsif ($node->eq (stream => 'error')) {
308     $self->handle_error ($node);
309 elmex 1.11
310 elmex 1.1 } else {
311     warn "Didn't understood stanza: '" . $node->name . "'";
312     }
313     }
314    
315 elmex 1.10 =head2 init ()
316 elmex 1.1
317     Initiate the XML stream.
318    
319     =cut
320    
321     sub init {
322     my ($self) = @_;
323     $self->{writer}->send_init_stream ($self->{language}, $self->{domain});
324     }
325    
326 elmex 1.10 =head2 is_connected ()
327    
328     Returns true if the connection is still connected and stanzas can be
329     sent.
330    
331     =cut
332    
333     sub is_connected {
334     my ($self) = @_;
335     $self->{authenticated}
336     }
337    
338 elmex 1.15 =head2 set_default_iq_timeout ($seconds)
339    
340     This sets the default timeout for IQ requests. If the timeout runs out
341     the request will be aborted and the callback called with a L<Net::XMPP2::Error::IQ> object
342     where the C<condition> method returns a special value (see also L<Net::XMPP2::Error::IQ::condition>).
343    
344     The default timeout for IQ is 60 seconds.
345    
346     =cut
347    
348     sub set_default_iq_timeout {
349     my ($self, $sec) = @_;
350     $self->{default_iq_timeout} = $sec;
351     }
352    
353 elmex 1.1 =head2 send_iq ($type, $create_cb, $result_cb, %attrs)
354    
355     This method sends an IQ XMPP request.
356    
357     Please take a look at the documentation for C<send_iq> in Net::XMPP2::Writer
358 elmex 1.15 about the meaning of C<$type>, C<$create_cb> and C<%attrs> (with the exception
359     of the 'timeout' key of C<%attrs>, see below).
360 elmex 1.1
361 elmex 1.15 C<$result_cb> will be called when a result was received or the timeout reached.
362     The first argument to C<$result_cb> will be a Net::XMPP2::Node instance
363     containing the IQ result stanza contents.
364 elmex 1.1
365     If the IQ resulted in a stanza error the second argument to C<$result_cb> will
366     be C<undef> (if the error type was not 'continue') and the third argument will
367 elmex 1.10 be a L<Net::XMPP2::Error::IQ> object.
368 elmex 1.1
369 elmex 1.15 The timeout can be set by C<set_default_iq_timeout> or passed seperatly
370     in the C<%attrs> array as the value for the key C<timeout> (timeout in seconds btw.).
371    
372 elmex 1.4 This method returns the newly generated id for this iq request.
373    
374 elmex 1.1 =cut
375    
376     sub send_iq {
377     my ($self, $type, $create_cb, $result_cb, %attrs) = @_;
378     my $id = $self->{iq_id}++;
379     $self->{iqs}->{$id} = $result_cb;
380 elmex 1.15
381     my $timeout = delete $attrs{timeout} || $self->{default_iq_timeout};
382     if ($timeout) {
383     $self->{iq_timers}->{$id} =
384 elmex 1.16 AnyEvent->timer (after => $timeout, sub {
385     delete $self->{iq_timers}->{$id};
386 elmex 1.15 my $cb = delete $self->{iqs}->{$id};
387 elmex 1.16 $cb->(undef, Net::XMPP2::Error::IQ->new)
388 elmex 1.15 });
389     }
390    
391 elmex 1.1 $self->{writer}->send_iq ($id, $type, $create_cb, %attrs);
392 elmex 1.4 $id
393     }
394    
395     =head2 reply_iq_result ($req_iq_node, $create_cb, %attrs)
396    
397     This method will generate a result reply to the iq request C<Net::XMPP2::Node>
398     in C<$req_iq_node>.
399    
400     Please take a look at the documentation for C<send_iq> in Net::XMPP2::Writer
401     about the meaning C<$create_cb> and C<%attrs>.
402    
403 elmex 1.6 Use C<$create_cb> to create the XML for the result.
404    
405 elmex 1.4 The type for this iq reply is 'result'.
406    
407     =cut
408    
409     sub reply_iq_result {
410     my ($self, $iqnode, $create_cb, %attrs) = @_;
411     $self->{writer}->send_iq ($iqnode->attr ('id'), 'result', $create_cb, %attrs);
412     }
413    
414     =head2 reply_iq_error ($req_iq_node, $error_type, $error, %attrs)
415    
416     This method will generate an error reply to the iq request C<Net::XMPP2::Node>
417     in C<$req_iq_node>.
418    
419     C<$error_type> is one of 'cancel', 'continue', 'modify', 'auth' and 'wait'.
420     C<$error> is one of the defined error conditions described in
421     L<Net::XMPP2::Writer::write_error_tag>.
422    
423     Please take a look at the documentation for C<send_iq> in Net::XMPP2::Writer
424 elmex 1.6 about the meaning of C<%attrs>.
425 elmex 1.4
426     The type for this iq reply is 'error'.
427    
428     =cut
429    
430     sub reply_iq_error {
431     my ($self, $iqnode, $errtype, $error, %attrs) = @_;
432    
433     $self->{writer}->send_iq (
434     $iqnode->attr ('id'), 'error',
435     sub { $self->{writer}->write_error_tag ($iqnode, $errtype, $error) },
436     %attrs
437     );
438 elmex 1.1 }
439    
440     sub handle_iq {
441     my ($self, $node) = @_;
442    
443 elmex 1.4 my $type = $node->attr ('type');
444    
445 elmex 1.15 my $id = $node->attr ('id');
446     delete $self->{iq_timers}->{$id} if defined $id;
447    
448 elmex 1.4 if ($type eq 'result') {
449 elmex 1.15 if (my $cb = delete $self->{iqs}->{$id}) {
450 elmex 1.1 $cb->($node);
451     }
452 elmex 1.9
453 elmex 1.4 } elsif ($type eq 'error') {
454 elmex 1.15 if (my $cb = delete $self->{iqs}->{$id}) {
455 elmex 1.1
456 elmex 1.10 my $error = Net::XMPP2::Error::IQ->new (node => $node);
457     $cb->(($error->type eq 'continue' ? $node : undef), $error);
458 elmex 1.1 }
459 elmex 1.4
460     } else {
461     my $handled = 0;
462 elmex 1.6 $self->event ("iq_${type}_request_xml" => $node, \$handled);
463 elmex 1.4
464     my @from;
465     push @from, (to => $node->attr ('from')) if $node->attr ('from');
466    
467     unless ($handled) {
468 elmex 1.5 $self->reply_iq_error ($node, undef, 'feature-not-implemented', @from);
469 elmex 1.4 }
470 elmex 1.1 }
471     }
472    
473 elmex 1.12 sub send_sasl_auth {
474     my ($self, @mechs) = @_;
475     $self->{writer}->send_sasl_auth (
476     (join ' ', map { $_->text } @mechs),
477     $self->{username}, $self->{domain}, $self->{password}
478     );
479     }
480    
481 elmex 1.13 =head2 request_inband_register_form ($finish_cb)
482    
483     This method starts a in-band-registration attempt. When finished C<$finish_cb>
484 elmex 1.17 will be called with the first argument being a L<Net::XMPP2::Ext::RegisterForm>
485 elmex 1.13 object (will be undef if an error occured) and the second an optional error
486 elmex 1.17 object of type L<Net::XMPP2::Error::Ext::Register> if an error occured.
487 elmex 1.13
488     =cut
489    
490     sub request_inband_register_form {
491     my ($self, $finish_cb) = @_;
492    
493     $self->send_iq (
494     get =>
495     sub {
496     my ($w) = @_;
497     $w->addPrefix (xmpp_ns ('register'), '');
498     $w->emptyTag ([qw/register query/]);
499     },
500     sub {
501     my ($node, $error) = @_;
502     my $form;
503 elmex 1.17 $form = Net::XMPP2::Ext::RegisterForm (node => $node, connection => $self)
504 elmex 1.13 unless $error;
505     $finish_cb->($form, $error);
506     }
507     );
508     }
509    
510     sub do_auto_register {
511     my ($self, $mechs) = @_;
512    
513     $self->request_inband_register_form (sub {
514     my ($form, $error) = @_;
515    
516     if ($error) {
517     $self->event (in_band_register_error => $error);
518    
519     } else {
520     if ($self->{register} ne 'manual') {
521     # of course this blows up if the form was more complicated
522     # any ideas?
523     $form->auto_submit (
524     username => $self->{username},
525     password => $self->{password},
526     cb => sub {
527     my ($form, $error) = @_;
528     if ($error) {
529     $self->event (auto_in_band_register_error => $error);
530     } else {
531     $self->event ('auto_in_band_register_ok');
532     $self->send_sasl_auth (@$mechs) if @$mechs;
533     }
534     }
535     );
536    
537     } else {
538     $self->event (
539     in_band_register_form =>
540     $form,
541     sub { $self->send_sasl_auth (@$mechs) if @$mechs }
542     )
543     }
544     }
545     });
546    
547     }
548    
549 elmex 1.1 sub handle_stream_features {
550     my ($self, $node) = @_;
551     my @mechs = $node->find_all ([qw/sasl mechanisms/], [qw/sasl mechanism/]);
552     my @bind = $node->find_all ([qw/bind bind/]);
553 elmex 1.2 my @tls = $node->find_all ([qw/tls starttls/]);
554 elmex 1.18 my @iqa = $node->find_all ([qw/iqauth auth/]);
555 elmex 1.13
556     # and yet another weird thingie: in XEP-0077 it's said that
557     # the register feature MAY be advertised by the server. That means:
558     # it MAY not be advertised even if it is available... so we don't
559     # care about it...
560     # my @reg = $node->find_all ([qw/register register/]);
561 elmex 1.1
562 elmex 1.5 if (not ($self->{disable_ssl}) && not ($self->{ssl_enabled}) && @tls) {
563 elmex 1.2 $self->{writer}->send_starttls;
564    
565 elmex 1.12 } elsif (not $self->{authenticated}) {
566 elmex 1.13 if ($self->{register}) {
567     $self->do_auto_register (\@mechs);
568 elmex 1.18 } elsif (@mechs) {
569     $self->send_sasl_auth (@mechs)
570     } elsif (@iqa) {
571     $self->do_iq_auth;
572 elmex 1.12 }
573 elmex 1.1
574     } elsif (@bind) {
575     $self->do_rebind ($self->{resource});
576     }
577     }
578    
579     sub handle_sasl_challenge {
580     my ($self, $node) = @_;
581     $self->{writer}->send_sasl_response ($node->text);
582     }
583    
584     sub handle_sasl_success {
585     my ($self, $node) = @_;
586     $self->{authenticated} = 1;
587     $self->{parser}->init;
588     $self->{writer}->init;
589     $self->{writer}->send_init_stream ($self->{language}, $self->{domain});
590     }
591    
592     sub handle_error {
593     my ($self, $node) = @_;
594 elmex 1.10 my $error = Net::XMPP2::Error::Stream->new (node => $node);
595    
596 elmex 1.18 $self->event (stream_error => $error);
597 elmex 1.1 $self->{writer}->send_end_of_stream;
598     }
599    
600 elmex 1.18 sub do_iq_auth {
601     my ($self) = @_;
602     # TODO
603     }
604    
605 elmex 1.4 =head2 send_presence ($type, $create_cb, %attrs)
606    
607     This method sends a presence stanza, for the meanings
608     of C<$type>, C<$create_cb> and C<%attrs> please take a look
609     at the documentation for L<Net::XMPP2::Writer::send_presence>.
610    
611     This methods does attach an id attribute to the message stanza and
612     will return the id that was used (so you can react on possible replies).
613    
614     =cut
615    
616     sub send_presence {
617     my ($self, $type, $create_cb, %attrs) = @_;
618     my $id = $self->{iq_id}++;
619     $self->{writer}->send_presence ($id, $type, $create_cb, %attrs);
620     $id
621     }
622    
623     =head2 send_message ($to, $type, $create_cb, %attrs)
624    
625     This method sends a presence stanza, for the meanings
626     of C<$to>, C<$type>, C<$create_cb> and C<%attrs> please take a look
627     at the documentation for L<Net::XMPP2::Writer::send_message>.
628    
629     This methods does attach an id attribute to the message stanza and
630     will return the id that was used (so you can react on possible replies).
631    
632     =cut
633    
634     sub send_message {
635     my ($self, $to, $type, $create_cb, %attrs) = @_;
636     my $id = $self->{iq_id}++;
637     $self->{writer}->send_message ($id, $to, $type, $create_cb, %attrs);
638     $id
639     }
640    
641 elmex 1.1 =head2 do_rebind ($resource)
642    
643     In case you got a C<bind_error> event and want to retry
644     binding you can call this function to set a new C<$resource>
645     and retry binding.
646    
647     If it fails again you can call this again. Becareful not to
648     end up in a loop!
649    
650     If binding was successful the C<stream_ready> event will be generated.
651    
652     =cut
653    
654     sub do_rebind {
655     my ($self, $resource) = @_;
656     $self->{resource} = $resource;
657     $self->send_iq (
658     set =>
659     sub {
660     my ($w) = @_;
661     if ($self->{resource}) {
662     $w->startTag ([xmpp_ns ('bind'), 'bind']);
663     $w->startTag ([xmpp_ns ('bind'), 'resource']);
664     $w->characters ($self->{resource});
665     $w->endTag;
666     $w->endTag;
667     } else {
668     $w->emptyTag ([xmpp_ns ('bind'), 'bind'])
669     }
670     },
671     sub {
672 elmex 1.13 my ($ret_iq, $error) = @_;
673 elmex 1.1
674 elmex 1.13 if ($error) {
675 elmex 1.10 my ($res) = $error->xml_node ()->find_all ([qw/bind bind/], [qw/bind resource/]);
676     $self->event (bind_error => $error, ($res ? $res : $self->{resource}));
677 elmex 1.1
678     } else {
679     my @jid = $ret_iq->find_all ([qw/bind bind/], [qw/bind jid/]);
680     my $jid = $jid[0]->text;
681     unless ($jid) { die "Got empty JID tag from server!\n" }
682     $self->{jid} = $jid;
683    
684     $self->event (stream_ready => $jid);
685     }
686     }
687     );
688     }
689    
690     =head2 jid
691    
692     After the stream has been bound to a resource the JID can be retrieved via this
693     method.
694    
695     =cut
696    
697     sub jid { $_[0]->{jid} }
698    
699 elmex 1.4 =head2 features
700    
701     Returns the last received <features> tag in form of an L<Net::XMPP2::Node> object.
702    
703     =cut
704    
705     sub features { $_[0]->{features} }
706    
707 elmex 1.1 =head1 EVENTS
708    
709     These events can be registered on with C<reg_cb>:
710    
711     =over 4
712    
713 elmex 1.11 =item stream_features => $node
714 elmex 1.1
715 elmex 1.4 This event is sent when a stream feature (<features>) tag is received. C<$node> is the
716     L<Net::XMPP2::Node> object that represents the <features> tag.
717 elmex 1.1
718     =item stream_ready => $jid
719    
720     This event is sent if the XML stream has been established (and
721     resources have been bound) and is ready for transmitting regular stanzas.
722    
723     C<$jid> is the bound jabber id.
724    
725 elmex 1.10 =item stream_error => $error
726 elmex 1.6
727     This event is sent if a XML stream error occured. C<$error>
728 elmex 1.10 is a L<Net::XMPP2::Error::Stream> object.
729 elmex 1.6
730 elmex 1.11 =item tls_error
731    
732     This event is emitted when a TLS error occured on TLS negotiation.
733     After this the connection will be disconnected.
734    
735     =item sasl_error => $error
736    
737     This event is emitted on SASL authentication error.
738    
739 elmex 1.10 =item bind_error => $error, $resource
740 elmex 1.6
741 elmex 1.10 This event is generated when the stream was unable to bind to
742     any or the in C<new> specified resource. C<$error> is a L<Net::XMPP2::Error::IQ>
743     object. C<$resource> is the errornous resource string or undef if none
744     was received.
745 elmex 1.6
746 elmex 1.10 The C<condition> of the C<$error> might be one of: 'bad-request',
747     'not-allowed' or 'conflict'.
748 elmex 1.1
749     Node: this is untested, i couldn't get the server to send a bind error
750     to test this.
751    
752     =item connect => $host, $port
753    
754     This event is generated when a successful connect was performed to
755     the domain passed to C<new>.
756    
757     Note: C<$host> and C<$port> might be different from the domain you passed to
758     C<new> if C<connect> performed a SRV RR lookup.
759    
760     If this connection is lost a C<disconnect> will be generated with the same
761     C<$host> and C<$port>.
762    
763     =item disconnect => $host, $port, $message
764    
765     This event is generated when the connection was lost or another error
766     occured while writing or reading from it.
767    
768     C<$message> is a humand readable error message for the failure.
769     C<$host> and C<$port> were the host and port we were connected to.
770    
771     Note: C<$host> and C<$port> might be different from the domain you passed to
772     C<new> if C<connect> performed a SRV RR lookup.
773    
774 elmex 1.6 =item presence_xml => $node
775 elmex 1.4
776     This event is sent when a presence stanza is received. C<$node> is the
777     L<Net::XMPP2::Node> object that represents the <presence> tag.
778    
779 elmex 1.6 =item message_xml => $node
780 elmex 1.4
781     This event is sent when a message stanza is received. C<$node> is the
782     L<Net::XMPP2::Node> object that represents the <message> tag.
783    
784 elmex 1.6 =item iq_set_request_xml => $node, $handled_ref
785 elmex 1.4
786 elmex 1.6 =item iq_get_request_xml => $node, $handled_ref
787 elmex 1.4
788     These events are sent when an iq request stanza of type 'get' or 'set' is received.
789     C<$type> will either be 'get' or 'set' and C<$node> will be the L<Net::XMPP2::Node>
790     object of the iq tag.
791    
792     If C<$$handled_ref> is true an event handler should not handle this message anymore.
793    
794     If one of the event handlers handled this message the scalar pointed at by
795     the reference in C<$handled_ref> should be set to 1 true value. If C<$$handled_ref>
796     is still false after all event handlers were executed an error iq will be generated.
797    
798 elmex 1.1 =back
799    
800     =head1 AUTHOR
801    
802     Robin Redeker, C<< <elmex at ta-sa.org> >>
803    
804     =head1 COPYRIGHT & LICENSE
805    
806     Copyright 2007 Robin Redeker, all rights reserved.
807    
808     This program is free software; you can redistribute it and/or modify it
809     under the same terms as Perl itself.
810    
811     =cut
812    
813     1; # End of Net::XMPP2