ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Net-XMPP2/lib/Net/XMPP2/Connection.pm
Revision: 1.27
Committed: Fri Jul 6 22:22:21 2007 UTC (19 years, 2 months ago) by elmex
Branch: MAIN
Changes since 1.26: +9 -1 lines
Log Message:
implemented dataforms - phew! that was a bullet of work

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