File Coverage

blib/lib/AnyEvent/XMPP/Connection.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             package AnyEvent::XMPP::Connection;
2 20     20   110 use strict;
  20         39  
  20         703  
3 20     20   1794 use AnyEvent;
  20         12480  
  20         390  
4 20     20   14598 use AnyEvent::XMPP::Parser;
  0            
  0            
5             use AnyEvent::XMPP::Writer;
6             use AnyEvent::XMPP::Util qw/split_jid join_jid simxml/;
7             use AnyEvent::XMPP::SimpleConnection;
8             use AnyEvent::XMPP::Namespaces qw/xmpp_ns/;
9             use AnyEvent::XMPP::Extendable;
10             use AnyEvent::XMPP::Error;
11             use Object::Event;
12             use Digest::SHA qw/sha1_hex/;
13             use Encode;
14              
15             our @ISA = qw/AnyEvent::XMPP::SimpleConnection Object::Event AnyEvent::XMPP::Extendable/;
16              
17             =head1 NAME
18              
19             AnyEvent::XMPP::Connection - XML stream that implements the XMPP RFC 3920.
20              
21             =head1 SYNOPSIS
22              
23             use AnyEvent::XMPP::Connection;
24              
25             my $con =
26             AnyEvent::XMPP::Connection->new (
27             username => "abc",
28             domain => "jabber.org",
29             resource => "AnyEvent::XMPP"
30             );
31              
32             $con->reg_cb (stream_ready => sub { print "XMPP stream ready!\n" });
33             $con->connect; # will do non-blocking connect
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, C and C.
39              
40             And receive events with the C event framework from the connection.
41              
42             If you need instant messaging stuff please take a look at C.
43              
44             =head1 METHODS
45              
46             =over 4
47              
48             =item B
49              
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             =item jid => $jid
62              
63             This can be used to set the settings C, C
64             (and optionally C) from a C<$jid>.
65              
66             =item username => $username
67              
68             This is your C<$username> (the userpart in the JID);
69              
70             Note: You have to take care that the stringprep profile for
71             nodes can be applied at: C<$username>. Otherwise the server
72             might signal an error. See L for utility functions
73             to check this.
74              
75             B This field has no effect if C is given!
76              
77             =item domain => $domain
78              
79             If you didn't provide a C (see above) you have to set the
80             C which you want to connect as (see above) and the
81             C<$domain> to connect to.
82              
83             B This field has no effect if C is given!
84              
85             =item resource => $resource
86              
87             If this argument is given C<$resource> will be passed as desired
88             resource on resource binding.
89              
90             Note: You have to take care that the stringprep profile for
91             resources can be applied at: C<$resource>. Otherwise the server
92             might signal an error. See L for utility functions
93             to check this.
94              
95             =item host => $host
96              
97             This parameter specifies the hostname where we are going
98             to connect to. The default for this is the C of the C.
99              
100             B To disable DNS SRV lookup you need to specify the port B
101             yourself. See C below.
102              
103             =item use_host_as_sasl_hostname => $bool
104              
105             This is a special parameter for people who might want to use GSSAPI SASL
106             mechanism. It will cause the value of the C parameter (see above) to be
107             passed to the SASL mechanisms, instead of the C of the JID.
108              
109             This flag is provided until support for XEP 0233 is deployed, which
110             will fix the hostname issue w.r.t. GSSAPI SASL.
111              
112             =item port => $port
113              
114             This is optional, the default value for C<$port> is 'xmpp-client=5222', which
115             will used as C<$service> argument to C of L.
116             B If you specify the port number here (instead of 'xmpp-client=5222'),
117             B DNS SRV lookup will be done when connecting.
118              
119             =item connect_timeout => $timeout
120              
121             This sets the connection timeout. If the socket connect takes too long
122             a C event will be generated with an appropriate error message.
123             If this argument is not given no timeout is installed for the connects.
124              
125             =item password => $password
126              
127             This is the password for the C above.
128              
129             =item disable_ssl => $bool
130              
131             If C<$bool> is true no SSL will be used.
132              
133             =item old_style_ssl => $bool
134              
135             If C<$bool> is true the TLS handshake will be initiated when the TCP
136             connection was established. This is useful if you have to connect to
137             an old Jabber server, with old-style SSL connections on port 5223.
138              
139             But that practice has been discouraged in XMPP, and a TLS handshake is done
140             after the XML stream has been established. Only use this option if you know
141             what you are doing.
142              
143             =item disable_sasl => $bool
144              
145             If C<$bool> is true SASL will NOT be used to authenticate with the server, even
146             if it advertises SASL through stream features. Alternative authentication
147             methods will be used, such as IQ Auth (XEP-0078) if the server offers it.
148              
149             =item disable_iq_auth => $bool
150              
151             This disables the use of IQ Auth (XEP-0078) for authentication, you might want
152             to exclude it because it's deprecated and insecure. (However, I want to reach a
153             maximum in compatibility with L so I'm not disabling this by
154             default.
155              
156             See also C below.
157              
158             =item anal_iq_auth => $bool
159              
160             This enables the anal iq auth mechanism that will first look in the stream
161             features before trying to start iq authentication. Yes, servers don't always
162             advertise what they can. I only implemented this option for my test suite.
163              
164             =item disable_old_jabber_authentication => $bool
165              
166             If C<$bool> is a true value, then the B old style authentication method
167             with B old jabber server won't be used when a start tag from the server
168             without version attribute is received.
169              
170             The B old style authentication method is per default enabled to ensure
171             maximum compatibility with old jabber implementations. The old method works as
172             follows: When a start tag is received from the server with no
173             'version' attribute IQ Auth (XEP-0078) will be initiated to authenticate with
174             the server.
175              
176             Please note that the old authentication method will fail if C
177             is true.
178              
179             =item stream_version_override => $version
180              
181             B Only use if you B know what you are doing!
182              
183             This will override the stream version which is sent in the XMPP stream
184             initiation element. This is currently only used by the tests which
185             set C<$version> to '0.9' for testing IQ authentication with ejabberd.
186              
187             =item whitespace_ping_interval => $interval
188              
189             This will set the whitespace ping interval (in seconds). The default interval
190             are 60 seconds. You can disable the whitespace ping by setting C<$interval> to
191             0.
192              
193             =back
194              
195             =cut
196              
197             sub new {
198             my $this = shift;
199             my $class = ref($this) || $this;
200             my $self =
201             $class->SUPER::new (
202             language => 'en',
203             stream_namespace => 'client',
204             whitespace_ping_interval => 60,
205             @_
206             );
207              
208             $self->{parser} = new AnyEvent::XMPP::Parser;
209             $self->{writer} = AnyEvent::XMPP::Writer->new (
210             write_cb => sub { $self->write_data ($_[0]) },
211             send_iq_cb => sub { my @cb; $self->event (send_iq_hook => (@_, \@cb)); return @cb },
212             send_msg_cb => sub { my @cb; $self->event (send_message_hook => (@_, \@cb)); return @cb },
213             send_pres_cb => sub { my @cb; $self->event (send_presence_hook => (@_, \@cb)); return @cb },
214             );
215              
216             $self->{parser}->set_stanza_cb (sub {
217             eval {
218             $self->handle_stanza (@_);
219             };
220             if ($@) {
221             $self->event (error =>
222             AnyEvent::XMPP::Error::Exception->new (
223             exception => $@, context => 'stanza handling'
224             )
225             );
226             }
227             });
228             $self->{parser}->set_error_cb (sub {
229             my ($ex, $data, $type) = @_;
230              
231             if ($type eq 'xml') {
232             my $pe = AnyEvent::XMPP::Error::Parser->new (exception => $_[0], data => $_[1]);
233             $self->event (xml_parser_error => $pe);
234             $self->disconnect ("xml error: $_[0], $_[1]");
235              
236             } else {
237             my $pe = AnyEvent::XMPP::Error->new (
238             text => "uncaught exception in stanza handling: $ex"
239             );
240             $self->event (uncaught_exception_error => $pe);
241             $self->disconnect ($pe->string);
242             }
243             });
244              
245             $self->{parser}->set_stream_cb (sub {
246             $self->{stream_id} = $_[0]->attr ('id');
247              
248             # This is some very bad "hack" for _very_ old jabber
249             # servers to work with AnyEvent::XMPP
250             if (not defined $_[0]->attr ('version')) {
251             $self->start_old_style_authentication
252             if (not $self->{disable_iq_auth})
253             && (not $self->{disable_old_jabber_authentication})
254             }
255             });
256              
257              
258             $self->{iq_id} = 1;
259             $self->{default_iq_timeout} = 60;
260              
261             $self->{disconnect_cb} = sub {
262             my ($host, $port, $message) = @_;
263             delete $self->{authenticated};
264             delete $self->{ssl_enabled};
265             $self->event (disconnect => $host, $port, $message);
266             $self->{disconnect_cb} = sub {};
267             delete $self->{writer};
268             $self->{parser}->cleanup;
269             delete $self->{parser};
270             };
271              
272             if ($self->{jid}) {
273             my ($user, $host, $res) = split_jid ($self->{jid});
274             $self->{username} = $user;
275             $self->{domain} = $host;
276             $self->{resource} = $res if defined $res;
277             }
278              
279             $self->{host} = $self->{domain} unless defined $self->{host};
280             $self->{port} = 'xmpp-client=5222' unless defined $self->{port};
281              
282             my $proxy_cb = sub {
283             my ($self, $er) = @_;
284             $self->event (error => $er);
285             };
286              
287             $self->reg_cb (
288             xml_parser_error => $proxy_cb,
289             sasl_error => $proxy_cb,
290             stream_error => $proxy_cb,
291             bind_error => $proxy_cb,
292             iq_auth_error => $proxy_cb,
293             iq_result_cb_exception => sub {
294             my ($self, $ex) = @_;
295             $self->event (error =>
296             AnyEvent::XMPP::Error::Exception->new (
297             exception => $ex, context => 'iq result callback execution'
298             )
299             );
300             },
301             tls_error => sub {
302             my ($self) = @_;
303             $self->event (error =>
304             AnyEvent::XMPP::Error->new (text => 'tls_error: tls negotiation failed')
305             );
306             },
307             iq_xml => sub { shift @_; $self->handle_iq (@_) }
308             );
309              
310             if ($self->{whitespace_ping_interval} > 0) {
311             $self->reg_cb (
312             stream_ready => sub {
313             my ($self) = @_;
314             $self->_start_whitespace_ping;
315             $self->unreg_me;
316             },
317             disconnect => sub {
318             $self->_stop_whitespace_ping;
319             $self->unreg_me;
320             }
321             );
322             }
323              
324             $self->set_exception_cb (sub {
325             my ($ex) = @_;
326             $self->event (error =>
327             AnyEvent::XMPP::Error::Exception->new (
328             exception => $ex, context => 'event callback'
329             )
330             );
331             });
332              
333             return $self;
334             }
335              
336             =item B
337              
338             Try to connect (non blocking) to the domain and port passed in C.
339              
340             The connection is performed non blocking, so this method will just
341             trigger the connection process. The event C will be emitted
342             when the connection was successfully established.
343              
344             If the connection try was not successful a C event
345             will be generated with an error message.
346              
347             NOTE: Please note that you can't reconnect a L
348             object. You need to recreate it if you want to reconnect.
349              
350             NOTE: The "XML" stream initiation is sent when the connection
351             was successfully connected.
352              
353              
354             =cut
355              
356             sub connect {
357             my ($self) = @_;
358             $self->SUPER::connect ($self->{host}, $self->{port}, $self->{connect_timeout});
359             }
360              
361             sub connected {
362             my ($self) = @_;
363              
364             if ($self->{old_style_ssl}) {
365             $self->enable_ssl;
366             }
367              
368             $self->init;
369             $self->event (connect => $self->{peer_host}, $self->{peer_port});
370             }
371              
372             sub send_buffer_empty {
373             my ($self) = @_;
374             $self->event ('send_buffer_empty');
375             }
376              
377             sub handle_data {
378             my ($self, $buf) = @_;
379             $self->event (debug_recv => $$buf);
380             $self->{parser}->feed (substr $$buf, 0, (length $$buf), '');
381             }
382              
383             sub debug_wrote_data {
384             my ($self, $data) = @_;
385             $self->event (debug_send => $data);
386             }
387              
388             sub write_data {
389             my ($self, $data) = @_;
390             $self->event (send_stanza_data => $data);
391             $self->SUPER::write_data ($data);
392             }
393              
394             sub default_namespace {
395             return 'client';
396             }
397              
398             sub handle_stanza {
399             my ($self, $p, $node) = @_;
400              
401             if (not defined $node) { # got stream end
402             $self->disconnect ("end of 'XML' stream encountered");
403             return;
404             }
405              
406             my $stop = 0;
407             $self->event (recv_stanza_xml => $node, \$stop);
408             $stop and return;
409              
410             my $def_ns = $self->default_namespace;
411              
412             if ($node->eq (stream => 'features')) {
413             $self->event (stream_features => $node);
414             $self->{features} = $node;
415             $self->handle_stream_features ($node);
416              
417             } elsif ($node->eq (tls => 'proceed')) {
418             $self->enable_ssl;
419             $self->{parser}->init;
420             $self->{writer}->init;
421             $self->{writer}->send_init_stream (
422             $self->{language}, $self->{domain}, $self->{stream_namespace}
423             );
424              
425             } elsif ($node->eq (tls => 'failure')) {
426             $self->event ('tls_error');
427             $self->disconnect ('TLS failure on TLS negotiation.');
428              
429             } elsif ($node->eq (sasl => 'challenge')) {
430             $self->handle_sasl_challenge ($node);
431              
432             } elsif ($node->eq (sasl => 'success')) {
433             $self->handle_sasl_success ($node);
434              
435             } elsif ($node->eq (sasl => 'failure')) {
436             my $error = AnyEvent::XMPP::Error::SASL->new (node => $node);
437             $self->event (sasl_error => $error);
438             $self->disconnect ('SASL authentication failure: ' . $error->string);
439              
440             } elsif ($node->eq ($def_ns => 'iq')) {
441             $self->event (iq_xml => $node);
442              
443             } elsif ($node->eq ($def_ns => 'message')) {
444             $self->event (message_xml => $node);
445              
446             } elsif ($node->eq ($def_ns => 'presence')) {
447             $self->event (presence_xml => $node);
448              
449             } elsif ($node->eq (stream => 'error')) {
450             $self->handle_error ($node);
451             }
452             }
453              
454             # This method is private
455              
456             sub init {
457             my ($self) = @_;
458             $self->{writer}->send_init_stream ($self->{language}, $self->{domain}, $self->{stream_namespace}, $self->{stream_version_override});
459             }
460              
461             =item B
462              
463             Returns true if the connection is still connected and stanzas can be
464             sent.
465              
466             =cut
467              
468             sub is_connected {
469             my ($self) = @_;
470             $self->{authenticated}
471             }
472              
473             =item B
474              
475             This sets the default timeout for IQ requests. If the timeout runs out
476             the request will be aborted and the callback called with a L object
477             where the C method returns a special value (see also C method of L).
478              
479             The default timeout for IQ is 60 seconds.
480              
481             =cut
482              
483             sub set_default_iq_timeout {
484             my ($self, $sec) = @_;
485             $self->{default_iq_timeout} = $sec;
486             }
487              
488             =item B
489              
490             This method sends an IQ XMPP B.
491              
492             If you want to B to a IQ request you received via the C,
493             and C events you have to use the C or
494             C methods documented below.
495              
496             Please take a look at the documentation for C in AnyEvent::XMPP::Writer
497             about the meaning of C<$type>, C<$create_cb> and C<%attrs> (with the exception
498             of the 'timeout' key of C<%attrs>, see below).
499              
500             C<$result_cb> will be called when a result was received or the timeout reached.
501             The first argument to C<$result_cb> will be a AnyEvent::XMPP::Node instance
502             containing the IQ result stanza contents.
503              
504             If the IQ resulted in a stanza error the second argument to C<$result_cb> will
505             be C (if the error type was not 'continue') and the third argument will
506             be a L object.
507              
508             The timeout can be set by C or passed separately
509             in the C<%attrs> array as the value for the key C (timeout in seconds btw.).
510              
511             This method returns the newly generated id for this iq request.
512              
513             =cut
514              
515             sub send_iq {
516             my ($self, $type, $create_cb, $result_cb, %attrs) = @_;
517             my $id = $self->{iq_id}++;
518             $self->{iqs}->{$id} = $result_cb;
519              
520             my $timeout = delete $attrs{timeout} || $self->{default_iq_timeout};
521             if ($timeout) {
522             $self->{iq_timers}->{$id} =
523             AnyEvent->timer (after => $timeout, cb => sub {
524             delete $self->{iq_timers}->{$id};
525             my $cb = delete $self->{iqs}->{$id};
526             $cb->(undef, AnyEvent::XMPP::Error::IQ->new)
527             });
528             }
529              
530             $self->{writer}->send_iq ($id, $type, $create_cb, %attrs);
531             $id
532             }
533              
534             =item B
535              
536             This method returns the next IQ id that will be used.
537              
538             =cut
539              
540             sub next_iq_id {
541             $_[0]->{iq_id};
542             }
543              
544             =item B
545              
546             This method will generate a result reply to the iq request C
547             in C<$req_iq_node>.
548              
549             Please take a look at the documentation for C in L
550             about the meaning C<$create_cb> and C<%attrs>.
551              
552             Use C<$create_cb> to create the XML for the result.
553              
554             The type for this iq reply is 'result'.
555              
556             The C attribute of the reply stanza will be set to the C
557             attribute of the C<$req_iq_node>. If C<$req_iq_node> had no C
558             node it won't be set. If you want to overwrite the C field just
559             pass it via C<%attrs>.
560              
561             =cut
562              
563             sub reply_iq_result {
564             my ($self, $iqnode, $create_cb, %attrs) = @_;
565            
566             return $self->_reply_iq(
567             $iqnode,
568             'result',
569             $create_cb,
570             %attrs
571             );
572             }
573              
574             =item B
575              
576             This method will generate an error reply to the iq request C
577             in C<$req_iq_node>.
578              
579             C<$error_type> is one of 'cancel', 'continue', 'modify', 'auth' and 'wait'.
580             C<$error> is one of the defined error conditions described in
581             C method of L.
582              
583             Please take a look at the documentation for C in AnyEvent::XMPP::Writer
584             about the meaning of C<%attrs>.
585              
586             The type for this iq reply is 'error'.
587              
588             The C attribute of the reply stanza will be set to the C
589             attribute of the C<$req_iq_node>. If C<$req_iq_node> had no C
590             node it won't be set. If you want to overwrite the C field just
591             pass it via C<%attrs>.
592              
593             =cut
594              
595             sub reply_iq_error {
596             my ($self, $iqnode, $errtype, $error, %attrs) = @_;
597              
598             return $self->_reply_iq(
599             $iqnode,
600             'error',
601             sub { $self->{writer}->write_error_tag ($iqnode, $errtype, $error) },
602             %attrs
603             );
604             }
605              
606             sub _reply_iq {
607             my ($self, $iqnode, $type, $create_cb, %attrs) = @_;
608              
609             return $self->{writer}->send_iq (
610             $iqnode->attr ('id'), $type, $create_cb,
611             (defined $iqnode->attr ('from') ? (to => $iqnode->attr ('from')) : ()),
612             (defined $iqnode->attr ('to') ? (from => $iqnode->attr ('to')) : ()),
613             %attrs
614             );
615             }
616              
617             sub handle_iq {
618             my ($self, $node) = @_;
619              
620             my $type = $node->attr ('type');
621              
622             my $id = $node->attr ('id');
623             delete $self->{iq_timers}->{$id} if defined $id;
624              
625             if ($type eq 'result') {
626             if (my $cb = delete $self->{iqs}->{$id}) {
627             eval {
628             $cb->($node);
629             };
630             if ($@) { $self->event (iq_result_cb_exception => $@) }
631             }
632              
633             } elsif ($type eq 'error') {
634             if (my $cb = delete $self->{iqs}->{$id}) {
635              
636             my $error = AnyEvent::XMPP::Error::IQ->new (node => $node);
637              
638             eval {
639             $cb->(($error->type eq 'continue' ? $node : undef), $error);
640             };
641             if ($@) { $self->event (iq_result_cb_exception => $@) }
642             }
643              
644             } else {
645             my $handled = 0;
646             $self->event ("iq_${type}_request_xml" => $node, \$handled);
647             $handled or $self->reply_iq_error ($node, undef, 'service-unavailable');
648             }
649             }
650              
651             sub send_sasl_auth {
652             my ($self, @mechs) = @_;
653              
654             for (qw/username password domain/) {
655             die "No '$_' argument given to new, but '$_' is required\n"
656             unless defined $self->{$_};
657             }
658              
659             $self->{writer}->send_sasl_auth (
660             [map { $_->text } @mechs],
661             $self->{username},
662             ($self->{use_host_as_sasl_hostname}
663             ? $self->{host}
664             : $self->{domain}),
665             $self->{password}
666             );
667             }
668              
669             sub handle_stream_features {
670             my ($self, $node) = @_;
671             my @bind = $node->find_all ([qw/bind bind/]);
672             my @tls = $node->find_all ([qw/tls starttls/]);
673              
674             # and yet another weird thingie: in XEP-0077 it's said that
675             # the register feature MAY be advertised by the server. That means:
676             # it MAY not be advertised even if it is available... so we don't
677             # care about it...
678             # my @reg = $node->find_all ([qw/register register/]);
679              
680             if (not ($self->{disable_ssl}) && not ($self->{ssl_enabled}) && @tls) {
681             $self->{writer}->send_starttls;
682              
683             } elsif (not $self->{authenticated}) {
684             my $continue = 1;
685             $self->event (stream_pre_authentication => \$continue);
686             if ($continue) {
687             $self->authenticate;
688             }
689              
690             } elsif (@bind) {
691             $self->do_rebind ($self->{resource});
692             }
693             }
694              
695             =item B
696              
697             This method should be called after the C event
698             was emitted to continue authentication of the stream.
699              
700             Usually this method only has to be called when you want to register before
701             you authenticate. See also the documentation of the C
702             event below.
703              
704             =cut
705              
706             sub authenticate {
707             my ($self) = @_;
708             my $node = $self->{features};
709             my @mechs = $node->find_all ([qw/sasl mechanisms/], [qw/sasl mechanism/]);
710              
711             # Yes, and also iq-auth isn't correctly advertised in the
712             # stream features! We all love the depreacted XEP-0078, eh?
713             my @iqa = $node->find_all ([qw/iqauth auth/]);
714              
715             if (not ($self->{disable_sasl}) && @mechs) {
716             $self->send_sasl_auth (@mechs)
717              
718             } elsif (not $self->{disable_iq_auth}) {
719             if ($self->{anal_iq_auth} && !@iqa) {
720             if (@iqa) {
721             $self->do_iq_auth;
722             } else {
723             die "No authentication method left after anal iq auth, neither SASL or IQ auth.\n";
724             }
725             } else {
726             $self->do_iq_auth;
727             }
728              
729             } else {
730             die "No authentication method left, neither SASL or IQ auth.\n";
731             }
732             }
733              
734             sub handle_sasl_challenge {
735             my ($self, $node) = @_;
736             $self->{writer}->send_sasl_response ($node->text);
737             }
738              
739             sub handle_sasl_success {
740             my ($self, $node) = @_;
741             $self->{authenticated} = 1;
742             $self->{parser}->init;
743             $self->{writer}->init;
744             $self->{writer}->send_init_stream (
745             $self->{language}, $self->{domain}, $self->{stream_namespace}
746             );
747             }
748              
749             sub handle_error {
750             my ($self, $node) = @_;
751             my $error = AnyEvent::XMPP::Error::Stream->new (node => $node);
752              
753             $self->event (stream_error => $error);
754             $self->{writer}->send_end_of_stream;
755             }
756              
757             # This is a hack for jabberd 1.4.2, VERY OLD Jabber stuff.
758             sub start_old_style_authentication {
759             my ($self) = @_;
760              
761             $self->{features}
762             = AnyEvent::XMPP::Node->new (
763             'http://etherx.jabber.org/streams', 'features', [], $self->{parser}
764             );
765              
766             my $continue = 1;
767             $self->event (stream_pre_authentication => \$continue);
768             if ($continue) {
769             $self->do_iq_auth;
770             }
771             }
772              
773             sub do_iq_auth {
774             my ($self) = @_;
775              
776             if ($self->{anal_iq_auth}) {
777             $self->send_iq (get => {
778             defns => 'auth', node => { ns => 'auth', name => 'query',
779             # heh, something i've seen on some ejabberd site:
780             # childs => [ { name => 'username', childs => [ $self->{username} ] } ]
781             }
782             }, sub {
783             my ($n, $e) = @_;
784             if ($e) {
785             $self->event (iq_auth_error =>
786             AnyEvent::XMPP::Error::IQAuth->new (context => 'iq_error', iq_error => $e)
787             );
788             } else {
789             my $fields = {};
790             my (@query) = $n->find_all ([qw/auth query/]);
791             if (@query) {
792             for (qw/username password digest resource/) {
793             if ($query[0]->find_all ([qw/auth/, $_])) {
794             $fields->{$_} = 1;
795             }
796             }
797              
798             $self->do_iq_auth_send ($fields);
799             } else {
800             $self->event (iq_auth_error =>
801             AnyEvent::XMPP::Error::IQAuth->new (context => 'no_fields')
802             );
803             }
804             }
805             });
806             } else {
807             $self->do_iq_auth_send ({ username => 1, password => 1, resource => 1 });
808             }
809             }
810              
811             sub do_iq_auth_send {
812             my ($self, $fields) = @_;
813              
814             for (qw/username password resource/) {
815             die "No '$_' argument given to new, but '$_' is required\n"
816             unless defined $self->{$_};
817             }
818              
819             my $do_resource = $fields->{resource};
820             my $password = $self->{password};
821              
822             if ($fields->{digest}) {
823             my $out_password = encode ("UTF-8", $password);
824             my $out = lc sha1_hex ($self->stream_id () . $out_password);
825             $fields = {
826             username => $self->{username},
827             digest => $out,
828             }
829              
830             } else {
831             $fields = {
832             username => $self->{username},
833             password => $password
834             }
835             }
836              
837             if ($do_resource && defined $self->{resource}) {
838             $fields->{resource} = $self->{resource}
839             }
840              
841             $self->send_iq (set => {
842             defns => 'auth',
843             node => { ns => 'auth', name => 'query', childs => [
844             map { { name => $_, childs => [ $fields->{$_} ] } } reverse sort keys %$fields
845             ]}
846             }, sub {
847             my ($n, $e) = @_;
848             if ($e) {
849             $self->event (iq_auth_error =>
850             AnyEvent::XMPP::Error::IQAuth->new (context => 'iq_error', iq_error => $e)
851             );
852             } else {
853             $self->{authenticated} = 1;
854             $self->{jid} = join_jid ($self->{username}, $self->{domain}, $self->{resource});
855             $self->event (stream_ready => $self->{jid});
856             }
857             });
858             }
859              
860             =item B
861              
862             This method sends a presence stanza, for the meanings
863             of C<$type>, C<$create_cb> and C<%attrs> please take a look
864             at the documentation for C method of L.
865              
866             This methods does attach an id attribute to the presence stanza and
867             will return the id that was used (so you can react on possible replies).
868              
869             =cut
870              
871             sub send_presence {
872             my ($self, $type, $create_cb, %attrs) = @_;
873             my $id = $self->{iq_id}++;
874             $self->{writer}->send_presence ($id, $type, $create_cb, %attrs);
875             $id
876             }
877              
878             =item B
879              
880             This method sends a message stanza, for the meanings
881             of C<$to>, C<$type>, C<$create_cb> and C<%attrs> please take a look
882             at the documentation for C method of L.
883              
884             This methods does attach an id attribute to the message stanza and
885             will return the id that was used (so you can react on possible replies).
886              
887             =cut
888              
889             sub send_message {
890             my ($self, $to, $type, $create_cb, %attrs) = @_;
891             my $id = delete $attrs{id} || $self->{iq_id}++;
892             $self->{writer}->send_message ($id, $to, $type, $create_cb, %attrs);
893             $id
894             }
895              
896             =item B
897              
898             In case you got a C event and want to retry
899             binding you can call this function to set a new C<$resource>
900             and retry binding.
901              
902             If it fails again you can call this again. Becareful not to
903             end up in a loop!
904              
905             If binding was successful the C event will be generated.
906              
907             =cut
908              
909             sub do_rebind {
910             my ($self, $resource) = @_;
911             $self->{resource} = $resource;
912             $self->send_iq (
913             set =>
914             sub {
915             my ($w) = @_;
916             if ($self->{resource}) {
917             simxml ($w,
918             defns => 'bind',
919             node => {
920             name => 'bind',
921             childs => [ { name => 'resource', childs => [ $self->{resource} ] } ]
922             }
923             )
924             } else {
925             simxml ($w, defns => 'bind', node => { name => 'bind' })
926             }
927             },
928             sub {
929             my ($ret_iq, $error) = @_;
930              
931             if ($error) {
932             # TODO: make bind error into a seperate error class?
933             if ($error->xml_node ()) {
934             my ($res) = $error->xml_node ()->find_all ([qw/bind bind/], [qw/bind resource/]);
935             $self->event (bind_error => $error, ($res ? $res : $self->{resource}));
936             } else {
937             $self->event (bind_error => $error);
938             }
939              
940             } else {
941             my @jid = $ret_iq->find_all ([qw/bind bind/], [qw/bind jid/]);
942             my $jid = $jid[0]->text;
943             unless ($jid) { die "Got empty JID tag from server!\n" }
944             $self->{jid} = $jid;
945              
946             $self->event (stream_ready => $jid);
947             }
948             }
949             );
950             }
951              
952              
953             sub _start_whitespace_ping {
954             my ($self) = @_;
955              
956             return unless $self->{whitespace_ping_interval} > 0;
957              
958             $self->{_ws_ping} =
959             AnyEvent->timer (after => $self->{whitespace_ping_interval}, cb => sub {
960             $self->{writer}->send_whitespace_ping;
961             $self->_start_whitespace_ping;
962             });
963             }
964              
965             sub _stop_whitespace_ping {
966             delete $_[0]->{_ws_ping};
967             }
968              
969              
970             =item B
971              
972             After the stream has been bound to a resource the JID can be retrieved via this
973             method.
974              
975             =cut
976              
977             sub jid { $_[0]->{jid} }
978              
979             =item B
980              
981             Returns the last received tag in form of an L object.
982              
983             =cut
984              
985             sub features { $_[0]->{features} }
986              
987             =item B
988              
989             This is the ID of this stream that was given us by the server.
990              
991             =cut
992              
993             sub stream_id { $_[0]->{stream_id} }
994              
995             =back
996              
997             =head1 EVENTS
998              
999             The L class is derived from the L class,
1000             and thus inherits the event callback registering system from it. Consult the
1001             documentation of L about more details.
1002              
1003             NODE: Every callback gets as it's first argument the L
1004             object. The further callback arguments are described in the following listing of
1005             events.
1006              
1007             These events can be registered on with C:
1008              
1009             =over 4
1010              
1011             =item stream_features => $node
1012              
1013             This event is sent when a stream feature () tag is received. C<$node> is the
1014             L object that represents the tag.
1015              
1016             =item stream_pre_authentication
1017              
1018             This event is emitted after TLS/SSL was initiated (if enabled) and before any
1019             authentication happened.
1020              
1021             The return value of the first event callback that is called decides what happens next.
1022             If it is true value the authentication continues. If it is undef or a false value
1023             authentication is stopped and you need to call C later.
1024             value
1025              
1026             This event is usually used when you want to do in-band registration,
1027             see also L.
1028              
1029             =item stream_ready => $jid
1030              
1031             This event is sent if the XML stream has been established (and
1032             resources have been bound) and is ready for transmitting regular stanzas.
1033              
1034             C<$jid> is the bound jabber id.
1035              
1036             =item error => $error
1037              
1038             This event is generated whenever some error occured.
1039             C<$error> is an instance of L.
1040             Trivial error reporting may look like this:
1041              
1042             $con->reg_cb (error => sub { warn "xmpp error: " . $_[1]->string . "\n" });
1043              
1044             Basically this event is a collect event for all other error events.
1045              
1046             =item stream_error => $error
1047              
1048             This event is sent if a XML stream error occured. C<$error>
1049             is a L object.
1050              
1051             =item xml_parser_error => $error
1052              
1053             This event is generated whenever the parser trips over XML that it can't
1054             read. C<$error> is a L object.
1055              
1056             =item tls_error
1057              
1058             This event is emitted when a TLS error occured on TLS negotiation.
1059             After this the connection will be disconnected.
1060              
1061             =item sasl_error => $error
1062              
1063             This event is emitted on SASL authentication error.
1064              
1065             =item iq_auth_error => $error
1066              
1067             This event is emitted when IQ authentication (XEP-0078) failed.
1068              
1069             =item bind_error => $error, $resource
1070              
1071             This event is generated when the stream was unable to bind to
1072             any or the in C specified resource. C<$error> is a L
1073             object. C<$resource> is the errornous resource string or undef if none
1074             was received.
1075              
1076             The C of the C<$error> might be one of: 'bad-request',
1077             'not-allowed' or 'conflict'.
1078              
1079             Node: this is untested, I couldn't get the server to send a bind error
1080             to test this.
1081              
1082             =item connect => $host, $port
1083              
1084             This event is generated when a successful TCP connect was performed to
1085             the domain passed to C.
1086              
1087             Note: C<$host> and C<$port> might be different from the domain you passed to
1088             C if C performed a SRV RR lookup.
1089              
1090             If this connection is lost a C will be generated with the same
1091             C<$host> and C<$port>.
1092              
1093             =item disconnect => $host, $port, $message
1094              
1095             This event is generated when the TCP connection was lost or another error
1096             occurred while writing or reading from it.
1097              
1098             C<$message> is a human readable error message for the failure.
1099             C<$host> and C<$port> were the host and port we were connected to.
1100              
1101             Note: C<$host> and C<$port> might be different from the domain you passed to
1102             C if C performed a SRV RR lookup.
1103              
1104             =item recv_stanza_xml => $node, $rstop
1105              
1106             This event is generated before any processing of a "XML" stanza happens.
1107             C<$node> is the node of the stanza that is being processed, it's of
1108             type L.
1109              
1110             This method might not be as handy for debugging purposes as C.
1111              
1112             If you want to handle the stanza yourself and don't want this module
1113             to take care of it set a true value to the scalar referenced by C<$rstop>.
1114              
1115             =item send_stanza_data => $data
1116              
1117             This event is generated shortly before data is sent to the socket.
1118             C<$data> contains a complete "XML" stanza or the end of stream closing
1119             tag. This method is useful for debugging purposes and I recommend
1120             using XML::Twig or something like that to display it nicely.
1121              
1122             See also the event C.
1123              
1124             =item debug_send => $data
1125              
1126             This method is invoked whenever data is written out. This event
1127             is mostly the same as C.
1128              
1129             =item debug_recv => $data
1130              
1131             This method is invoked whenever a chunk of data was received.
1132              
1133             It works to filter C<$data> through L for debugging
1134             display purposes sometimes, but as C<$data> is some arbitrary chunk
1135             of bytes you might get a XML parse error (did I already mention that XMPP's
1136             application of "XML" sucks?).
1137              
1138             So you might want to use C to detect
1139             complete stanzas. Unfortunately C doesn't have the
1140             bytes anymore and just a data structure (L).
1141              
1142             =item send_buffer_empty
1143              
1144             This event is VERY useful if you want to wait (or at least be notified)
1145             when the output buffer is empty. If you got a bunch of messages to sent
1146             or even one and you want to do something when the output buffer is empty,
1147             you can wait for this event. It is emitted every time the output buffer is
1148             completely written out to the kernel.
1149              
1150             Here is an example:
1151              
1152             $con->reg_cb (send_buffer_empty => sub {
1153             $con->disconnect ("wrote message, going to disconnect now...");
1154             });
1155             $con->send_message ("Test message!" => 'elmex@jabber.org', undef, 'chat');
1156              
1157             =item presence_xml => $node
1158              
1159             This event is sent when a presence stanza is received. C<$node> is the
1160             L object that represents the tag.
1161              
1162             If you want to overtake the handling of the stanza, see C
1163             below.
1164              
1165             =item message_xml => $node
1166              
1167             This event is sent when a message stanza is received. C<$node> is the
1168             L object that represents the tag.
1169              
1170             If you want to overtake the handling of the stanza, see C
1171             below.
1172              
1173             =item iq_xml => $node
1174              
1175             This event is emitted when a iq stanza arrives. C<$node> is the
1176             L object that represents the tag.
1177              
1178             If you want to overtake the handling of a stanza, you should
1179             register a callback for the C event and call the
1180             C method. See also L. This is an example:
1181              
1182             $con->reg_cb (before_iq_xml => sub {
1183             my ($con, $node) = @_;
1184              
1185             if (...) {
1186             # and stop_event will stop internal handling of the stanza:
1187             $con->stop_event;
1188             }
1189             });
1190              
1191             Please note that if you overtake handling of a stanza none of the internal
1192             handling of that stanza will be done. That means you won't get events
1193             like C anymore.
1194              
1195             =item iq_set_request_xml => $node, $rhandled
1196              
1197             =item iq_get_request_xml => $node, $rhandled
1198              
1199             These events are sent when an iq request stanza of type 'get' or 'set' is received.
1200             C<$type> will either be 'get' or 'set' and C<$node> will be the L
1201             object of the iq tag.
1202              
1203             To signal the stanza was handled set the scalar referenced by C<$rhandled>
1204             to a true value.
1205             If the stanza was not handled an error iq will be generated.
1206              
1207             =item iq_result_cb_exception => $exception
1208              
1209             If the C<$result_cb> of a C operation somehow threw a exception
1210             or failed this event will be generated.
1211              
1212             =item send_iq_hook => $id, $type, $attrs, \@create_cb
1213              
1214             This event lets you add any desired number of additional create callbacks
1215             to a IQ stanza that is about to be sent.
1216              
1217             C<$id>, C<$type> are described in the documentation of C of
1218             L. C<$attrs> is the hashref to the C<%attrs> hash that can
1219             be passed to C and also has the exact same semantics as described in
1220             the documentation of C.
1221              
1222             You can push values into C (as documented for C), for
1223             example a callback that fills the IQ.
1224              
1225             Example:
1226              
1227             # this appends a element to all outgoing IQs
1228             # and also a element to all outgoing IQs
1229             $con->reg_cb (send_iq_hook => sub {
1230             my ($con, $id, $type, $attrs, $create_cb) = @_;
1231             push @$create_cb, sub {
1232             my $w = shift; # $w is a XML::Writer instance
1233             $w->emptyTag ('test');
1234             };
1235             push @$create_cb, {
1236             node => { name => "test2" } # see also simxml() defined in AnyEvent::XMPP::Util
1237             };
1238             });
1239              
1240             =item send_message_hook => $id, $to, $type, $attrs, \@create_cb
1241              
1242             This event lets you add any desired number of additional create callbacks
1243             to a message stanza that is about to be sent.
1244              
1245             C<$id>, C<$to>, C<$type> and the hashref C<$attrs> are described in the documentation
1246             for C of L (C<$attrs> is C<%attrs> there).
1247              
1248             To actually append something you need to push into C as described in
1249             the C event above.
1250              
1251             =item send_presence_hook => $id, $type, $attrs, \@create_cb
1252              
1253             This event lets you add any desired number of additional create callbacks
1254             to a presence stanza that is about to be sent.
1255              
1256             C<$id>, C<$type> and the hashref C<$attrs> are described in the documentation
1257             for C of L (C<$attrs> is C<%attrs> there).
1258              
1259             To actually append something you need to push into C as described in
1260             the C event above.
1261              
1262             =back
1263              
1264             =head1 AUTHOR
1265              
1266             Robin Redeker, C<< >>, JID: C<< >>
1267              
1268             =head1 CONTRIBUTORS
1269              
1270             melo - minor fixes
1271              
1272             =head1 COPYRIGHT & LICENSE
1273              
1274             Copyright 2007, 2008 Robin Redeker, all rights reserved.
1275              
1276             This program is free software; you can redistribute it and/or modify it
1277             under the same terms as Perl itself.
1278              
1279             =cut
1280              
1281             1; # End of AnyEvent::XMPP