ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/Net-XMPP2/lib/Net/XMPP2/Ext/Disco.pm
Revision: 1.7
Committed: Wed Jul 11 13:34:54 2007 UTC (19 years, 2 months ago) by elmex
Branch: MAIN
Changes since 1.6: +1 -3 lines
Log Message:
added development client example

File Contents

# User Rev Content
1 elmex 1.3 package Net::XMPP2::Ext::Disco;
2 elmex 1.1 use Net::XMPP2::Namespaces qw/xmpp_ns/;
3 elmex 1.3 use Net::XMPP2::Ext::Disco::Items;
4     use Net::XMPP2::Ext::Disco::Info;
5 elmex 1.6 use Net::XMPP2::Ext;
6    
7     our @ISA = qw/Net::XMPP2::Ext/;
8 elmex 1.1
9     =head1 NAME
10    
11 elmex 1.5 Net::XMPP2::Ext::Disco - Service discovery manager class for XEP-0030
12 elmex 1.1
13     =head1 SYNOPSIS
14    
15     package foo;
16 elmex 1.3 use Net::XMPP2::Ext::Disco;
17 elmex 1.1
18     my $con = Net::XMPP2::IM::Connection->new (...);
19 elmex 1.7 $con->add_extension (my $disco = Net::XMPP2::Ext::Disco->new);
20 elmex 1.1 $disco->request_items ('romeo@montague.net',
21     node => 'http://jabber.org/protocol/tune',
22     cb => sub {
23     my ($disco, $response, $error) = @_;
24     if ($error) { print "ERROR".$error->string."\n" }
25     else {
26     ... do something with the $response ...
27     }
28     }
29     );
30    
31     =head1 DESCRIPTION
32    
33     This module represents a service discovery manager class.
34     You make instances of this class and get a handle to send
35     discovery requests like described in XEP-0030.
36    
37     It also allows you to setup a disco-info/items tree
38     that others can walk and also lets you publish disco information.
39    
40 elmex 1.6 This class is derived from L<Net::XMPP2::Ext> and can be added as extension to
41     objects that implement the L<Net::XMPP2::Extendable> interface or derive from
42     it.
43    
44 elmex 1.1 =head1 METHODS
45    
46 elmex 1.4 =over 4
47    
48     =item B<new (%args)>
49 elmex 1.1
50 elmex 1.6 Creates a new disco handle.
51 elmex 1.1
52     =cut
53    
54     sub new {
55     my $this = shift;
56     my $class = ref($this) || $this;
57     my $self = bless { @_ }, $class;
58     $self->init;
59     $self
60     }
61    
62     sub init {
63     my ($self) = @_;
64    
65     $self->set_identity (client => console => 'Net::XMPP2');
66    
67 elmex 1.6 $self->reg_cb (
68     iq_get_request_xml => sub {
69     my ($self, $con, $node, $handled_ref) = @_;
70     return 1 if $$handled_ref;
71 elmex 1.1
72 elmex 1.6 if ($self->handle_disco_query ($con, $node)) {
73     $$handled_ref = 1;
74     }
75 elmex 1.1
76 elmex 1.6 1
77     }
78     );
79 elmex 1.1 }
80    
81 elmex 1.4 =item B<set_identity ($category, $type, $name)>
82 elmex 1.1
83     This sets the identity of the top info node.
84     The default is: C<$category = "client">, C<$type = "console">
85     and C<$name = "Net::XMPP2">.
86    
87     C<$name> is optional and can be undef.
88    
89     For a list of valid identites look at:
90    
91     http://www.xmpp.org/registrar/disco-categories.html
92    
93     Valid identity types for C<$category = "client"> may be:
94    
95     bot
96     console
97     handheld
98     pc
99     phone
100     web
101    
102     =cut
103    
104     sub set_identity {
105     my ($self, $category, $type, $name) = @_;
106     $self->{iden}->{cat} = $category;
107     $self->{iden}->{type} = $type;
108     $self->{iden}->{name} = $name;
109     }
110    
111    
112 elmex 1.4 =item B<enable_feature ($uri)>
113 elmex 1.1
114     This method enables the feature C<$uri>, where C<$uri>
115     should be one of the values from the B<Name> column on:
116    
117     http://www.xmpp.org/registrar/disco-features.html
118    
119     These features are enabled by default:
120    
121     http://jabber.org/protocol/disco#info
122     http://jabber.org/protocol/disco#items
123    
124     =cut
125    
126     sub enable_feature {
127     my ($self, $feature) = @_;
128     $self->{feat}->{$feature} = 1
129     }
130    
131 elmex 1.4 =item B<disable_feature ($uri)>
132 elmex 1.1
133     This method enables the feature C<$uri>, where C<$uri>
134     should be one of the values from the B<Name> column on:
135    
136     http://www.xmpp.org/registrar/disco-features.html
137    
138     These features are enabled by default:
139    
140     http://jabber.org/protocol/disco#info
141     http://jabber.org/protocol/disco#items
142    
143     =cut
144    
145     sub disable_feature {
146     my ($self, $feature) = @_;
147     delete $self->{feat}->{$feature}
148     }
149    
150     sub write_feature {
151     my ($self, $w, $var) = @_;
152    
153     $w->emptyTag ([xmpp_ns ('disco_info'), 'feature'], var => $var);
154     }
155    
156     sub write_identity {
157     my ($self, $w, $cat, $type, $name) = @_;
158    
159     $w->emptyTag ([xmpp_ns ('disco_info'), 'identity'],
160     category => $cat,
161     type => $type,
162     (defined $name ? (name => $name) : ())
163     );
164     }
165    
166     sub handle_disco_query {
167 elmex 1.6 my ($self, $con, $node) = @_;
168 elmex 1.1
169     if ($node->find_all ([qw/disco_info query/])) {
170 elmex 1.6 $con->reply_iq_result (
171 elmex 1.1 $node, sub {
172     my ($w) = @_;
173    
174     if ($node->attr ('node')) {
175     $w->addPrefix (xmpp_ns ('disco_info'), '');
176     $w->emptyTag ([xmpp_ns ('disco_info'), 'query']);
177    
178     } else {
179     $w->addPrefix (xmpp_ns ('disco_info'), '');
180     $w->startTag ([xmpp_ns ('disco_info'), 'query']);
181     $self->write_identity ($w,
182     $self->{iden}->{cat},
183     $self->{iden}->{type},
184     $self->{iden}->{name},
185     );
186     $self->write_feature ($w, 'http://jabber.org/protocol/disco#info');
187     $self->write_feature ($w, 'http://jabber.org/protocol/disco#items');
188     $w->endTag;
189     }
190 elmex 1.6 },
191     to => $node->attr ('from')
192 elmex 1.1 );
193    
194     return 1
195    
196     } elsif ($node->find_all ([qw/disco_items query/])) {
197 elmex 1.6 $con->reply_iq_result (
198 elmex 1.1 $node, sub {
199     my ($w) = @_;
200    
201     if ($node->attr ('node')) {
202     $w->addPrefix (xmpp_ns ('disco_items'), '');
203     $w->emptyTag ([xmpp_ns ('disco_items'), 'query']);
204    
205     } else {
206     $w->addPrefix (xmpp_ns ('disco_items'), '');
207     $w->emptyTag ([xmpp_ns ('disco_items'), 'query']);
208     }
209 elmex 1.6 },
210     to => $node->attr ('from')
211 elmex 1.1 );
212    
213     return 1
214     }
215    
216     0
217     }
218    
219     sub DESTROY {
220     my ($self) = @_;
221     $self->{connection}->unreg_cb ($self->{cb_id})
222     }
223    
224 elmex 1.2
225 elmex 1.6 =item B<request_items ($con, $dest, $node, $cb)>
226 elmex 1.2
227     This method does send a items request to the JID entity C<$from>.
228     C<$node> is the optional node to send the request to, which can be
229     undef.
230 elmex 1.6 C<$con> must be an instance of L<Net::XMPP2::Connection> or a subclass of it.
231 elmex 1.2 The callback C<$cb> will be called when the request returns with 3 arguments:
232 elmex 1.3 the disco handle, an L<Net::XMPP2::Ext::Disco::Items> object (or undef)
233 elmex 1.2 and an L<Net::XMPP2::Error::IQ> object when an error occured and no items
234     were received.
235    
236 elmex 1.6 $disco->request_items ($con, 'a@b.com', undef, sub {
237 elmex 1.2 my ($disco, $items, $error) = @_;
238     die $error->string if $error;
239    
240     # do something with the items here ;_)
241     });
242    
243     =cut
244    
245     sub request_items {
246 elmex 1.6 my ($self, $con, $dest, $node, $cb) = @_;
247 elmex 1.2
248 elmex 1.6 $con->send_iq (
249 elmex 1.2 get => sub {
250     my ($w) = @_;
251     $w->addPrefix (xmpp_ns ('disco_items'), '');
252     $w->emptyTag ([xmpp_ns ('disco_items'), 'query'],
253     (defined $node ? (node => $node) : ())
254     );
255     },
256     sub {
257     my ($xmlnode, $error) = @_;
258     my $items;
259    
260     if ($xmlnode) {
261     my (@query) = $xmlnode->find_all ([qw/disco_items query/]);
262 elmex 1.3 $items = Net::XMPP2::Ext::Disco::Items->new (
263 elmex 1.2 jid => $dest,
264     node => $node,
265     xmlnode => $query[0]
266     )
267     }
268    
269     $cb->($self, $items, $error)
270     },
271     to => $dest
272     );
273     }
274    
275 elmex 1.6 =item B<request_info ($con, $dest, $node, $cb)>
276 elmex 1.2
277     This method does send a info request to the JID entity C<$from>.
278     C<$node> is the optional node to send the request to, which can be
279     undef.
280 elmex 1.6 C<$con> must be an instance of L<Net::XMPP2::Connection> or a subclass of it.
281 elmex 1.2 The callback C<$cb> will be called when the request returns with 3 arguments:
282 elmex 1.3 the disco handle, an L<Net::XMPP2::Ext::Disco::Info> object (or undef)
283 elmex 1.2 and an L<Net::XMPP2::Error::IQ> object when an error occured and no items
284     were received.
285    
286     $disco->request_info ('a@b.com', undef, sub {
287     my ($disco, $info, $error) = @_;
288     die $error->string if $error;
289    
290     # do something with info here ;_)
291     });
292    
293     =cut
294    
295     sub request_info {
296 elmex 1.6 my ($self, $con, $dest, $node, $cb) = @_;
297 elmex 1.2
298 elmex 1.6 $con->send_iq (
299 elmex 1.2 get => sub {
300     my ($w) = @_;
301     $w->addPrefix (xmpp_ns ('disco_info'), '');
302     $w->emptyTag ([xmpp_ns ('disco_info'), 'query'],
303     (defined $node ? (node => $node) : ())
304     );
305     },
306     sub {
307     my ($xmlnode, $error) = @_;
308     my $info;
309    
310     if ($xmlnode) {
311     my (@query) = $xmlnode->find_all ([qw/disco_info query/]);
312 elmex 1.3 $info = Net::XMPP2::Ext::Disco::Info->new (
313 elmex 1.2 jid => $dest,
314     node => $node,
315     xmlnode => $query[0]
316     )
317     }
318    
319     $cb->($self, $info, $error)
320     },
321     to => $dest
322     );
323     }
324    
325 elmex 1.4 =back
326    
327 elmex 1.1 =head1 AUTHOR
328    
329 elmex 1.4 Robin Redeker, C<< <elmex at ta-sa.org> >>, JID: C<< <elmex at jabber.org> >>
330 elmex 1.1
331     =head1 COPYRIGHT & LICENSE
332    
333     Copyright 2007 Robin Redeker, all rights reserved.
334    
335     This program is free software; you can redistribute it and/or modify it
336     under the same terms as Perl itself.
337    
338     =cut
339    
340     1;