ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Net-XMPP2/lib/Net/XMPP2/Connection.pm
Revision: 1.20
Committed: Wed Jul 4 16:05:22 2007 UTC (19 years, 2 months ago) by elmex
Branch: MAIN
Changes since 1.19: +22 -18 lines
Log Message:
major documentation refresh. preparing for release

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