ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Net-XMPP2/lib/Net/XMPP2/Connection.pm
Revision: 1.19
Committed: Tue Jun 26 08:33:07 2007 UTC (19 years, 3 months ago) by elmex
Branch: MAIN
Changes since 1.18: +4 -0 lines
Log Message:
added xml parser error callback

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