ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/AnyEvent-Porttracker/Porttracker.pm
(Generate patch)

Comparing cvsroot/AnyEvent-Porttracker/Porttracker.pm (file contents):
Revision 1.5 by root, Mon Nov 15 20:43:11 2010 UTC vs.
Revision 1.14 by root, Tue Nov 16 19:43:15 2010 UTC

3AnyEvent::Porttracker - Porttracker/PortIQ API client interface. 3AnyEvent::Porttracker - Porttracker/PortIQ API client interface.
4 4
5=head1 SYNOPSIS 5=head1 SYNOPSIS
6 6
7 use AnyEvent::Porttracker; 7 use AnyEvent::Porttracker;
8
9 my $api = new AnyEvent::Porttracker
10 host => "10.0.0.1",
11 user => "admin",
12 pass => "31331",
13 tls => 1,
14 ;
15
16 # Example 1
17 # a simple request: ping the server
18
19 $api->req ("ping", sub {
20 my ($api, $ok, $timestamp, $pid) = @_;
21 ...
22 });
23
24 # Example 2
25 # find all realms, start a discovery on all of them
26 # and wait until all discovery processes have finished
27
28 my $cv = AE::cv;
29
30 $cv->begin;
31 # find all realms
32 $api->req (realm_info => ["gid", "name"], sub {
33 my ($api, @realms) = @_;
34
35 # start discovery on all realms
36 for my $realm (@realms) {
37 my ($gid, $name) = @$realm;
38
39 $cv->begin;
40 $api->req (realm_discover => $gid, sub {
41 warn "discovery for realm '$name' finished\n";
42 $cv->end;
43 });
44 }
45
46 $cv->end;
47 });
48
49 $cv->recv;
50
51 # Example 3
52 # subscribe to realm_poll_stop events and report each occurance
53
54 $api->req (subscribe => "realm_poll_stop", sub {});
55 $api->on (realm_poll_stop_event => sub {
56 my ($api, $gid) = @_;
57 warn "this just in: poll for realm <$gid> finished.\n";
58 });
8 59
9=head1 DESCRIPTION 60=head1 DESCRIPTION
10 61
11Porttracker (L<http://www.porttracker.com/>) is a product that (among 62Porttracker (L<http://www.porttracker.com/>) is a product that (among
12other things) scans switches and routers in a network and gives a coherent 63other things) scans switches and routers in a network and gives a coherent
51 102
52use MIME::Base64 (); 103use MIME::Base64 ();
53use Digest::HMAC_MD6 (); 104use Digest::HMAC_MD6 ();
54use JSON (); 105use JSON ();
55 106
56our $VERSION = '0.0'; 107our $VERSION = '0.1';
57 108
58sub call { 109sub call {
59 my ($self, $type, @args) = @_; 110 my ($self, $type, @args) = @_;
60 111
61 $self->{$type} 112 $self->{$type}
93=item user => $string, pass => $string 144=item user => $string, pass => $string
94 145
95These are the username and password to use when authentication is required 146These are the username and password to use when authentication is required
96(which it is in almost all cases, so these keys are normally mandatory). 147(which it is in almost all cases, so these keys are normally mandatory).
97 148
98=item tls => ... 149=item tls => $bool
99 150
100#TODO# 151Enables or disables TLS (default: disables). When enabled, then the
152connection will try to handshake a TLS connection before logging in. If
153unsuccessful a fatal error will be raised.
154
155Since most Porttracker/PortIQ boxes will not have a sensible/verifiable
156certificate, no attempt at verifying it will be done (which means
157man-in-the-middle-attacks will be trivial). If you want some form of
158verification you need to provide your own C<tls_ctx> object with C<<
159verify => 1, verify_peername => [1, 1, 1] >> or whatever verification mode
160you wish to use.
161
162=item tls_ctx => $tls_ctx
163
164The L<AnyEvent::TLS> object to use. See C<tls>, above.
101 165
102=item on_XYZ => $coderef 166=item on_XYZ => $coderef
103 167
104You can specify event callbacks either by subclassing and overriding the 168You can specify event callbacks either by sub-classing and overriding the
105respective methods or by specifying coderefs as key-value pairs when 169respective methods or by specifying code-refs as key-value pairs when
106constructing the object. 170constructing the object. You add or remove event handlers at any time with
171the C<event> method.
107 172
108=back 173=back
109 174
110=cut 175=cut
111 176
113 my $class = shift; 178 my $class = shift;
114 179
115 my $self = bless { 180 my $self = bless {
116 id => "a", 181 id => "a",
117 ids => [], 182 ids => [],
118 queue => [], # ininitially queue everything 183 queue => [], # initially queue everything
119 @_, 184 @_,
120 }, $class; 185 }, $class;
121 186
122 { 187 {
123 Scalar::Util::weaken (my $self = $self); 188 Scalar::Util::weaken (my $self = $self);
124 189
125 $self->{hdl} = new AnyEvent::Handle 190 $self->{hdl} = new AnyEvent::Handle
126 connect => [$self->{host}, $self->{port} || "porttracker=55"], 191 connect => [$self->{host}, $self->{port} || "porttracker=55"],
127 on_error => sub { 192 on_error => sub {
128 $self->error (); 193 $self->error ($_[2]);
129 }, 194 },
130 on_connect => sub { 195 on_connect => sub {
131 if ($self->{tls}) { 196 if ($self->{tls}) {
132 $self->_req (start_tls => sub { 197 $self->_req (start_tls => sub {
133 $_[1] 198 $_[1]
169} 234}
170 235
171sub error { 236sub error {
172 my ($self, $msg) = @_; 237 my ($self, $msg) = @_;
173 238
174 call on_error => $msg; 239 call $self, on_error => $msg;
175 240
176 () 241 ()
177} 242}
178 243
179sub _req { 244sub _req {
188 my $msg = JSON::encode_json \@_; 253 my $msg = JSON::encode_json \@_;
189 254
190 $self->{hdl}->push_write ($msg); 255 $self->{hdl}->push_write ($msg);
191} 256}
192 257
193=item $api->req ($type => @args, $callback->($api, @args)) 258=item $api->req ($type => @args, $callback->($api, @reply))
194 259
195Sends a generic request of type C<$type> to the server. When the server 260Sends a generic request of type C<$type> to the server. When the server
196responds, the API object and the response arguments are passed to the 261responds, the API object and the response arguments (without the success
197callback, which is the last argument to this method. 262status) are passed to the callback, which is the last argument to this
263method.
264
265If the request fails, then a fatal error will be raised. If you want to
266handle failures gracefully, you need to use C<< ->req_failok >> instead.
198 267
199The available requests are documented in the Porttracker API 268The available requests are documented in the Porttracker API
200documentation (a copy of which is included in this module as 269documentation (a copy of which is included in this module as
201L<AnyEvent::Porttracker::protocol>. 270L<AnyEvent::Porttracker::protocol>.
202 271
228 }); 297 });
229 298
230=cut 299=cut
231 300
232sub req { 301sub req {
302 my $cb = pop;
303 push @_, sub {
304 splice @_, 1, 1
305 or $_[0]->error ($_[1]);
306
307 &$cb
308 };
309
233 $_[0]{queue} 310 $_[0]{queue}
234 ? push @{ $_[0]{queue} }, [@_] 311 ? push @{ $_[0]{queue} }, [@_]
235 : &_req 312 : &_req
236} 313}
237 314
315=item $api->req_failok ($type => @args, $callback->($api, $success, @reply))
316
317Just like C<< ->req >>, with two differences: first, a failure will not
318raise an error, second, the initial status reply which indicates success
319or failure is not removed before calling the callback.
320
321=cut
322
323sub req_failok {
324 $_[0]{queue}
325 ? push @{ $_[0]{queue} }, [@_]
326 : &_req
327}
328
329=item $api->on (XYZ => $callback)
330
331Overwrites any currently registered handler for C<on_XYZ> or
332installs a new one. Or, when C<$callback> is undef, unregisters any
333currently-registered handler.
334
335Example: replace/set the handler for C<on_discover_stop_event>.
336
337 $api->on (discover_stop_event => sub {
338 my ($api, $gid) = @_;
339 ...
340 });
341
342=cut
343
344sub on {
345 my $self = shift;
346
347 while (@_) {
348 my ($event, $cb) = splice @_, 0, 2;
349 $event =~ s/^on_//;
350
351 $self->{"on_$event"} = $cb;
352 }
353}
354
238sub on_start_tls_notify { 355sub on_start_tls_notify {
239 my ($self) = @_; 356 my ($self) = @_;
240 357
241 $self->{hdl}->starttls ("connect"); 358 $self->{hdl}->starttls (connect => $self->{tls_ctx});
242 $self->{tls} ||= 1; 359 $self->{tls} ||= 1;
243 360
244 $self->_login; 361 $self->_login;
245} 362}
246 363
338 455
339 $msg =~ s/\n$//; 456 $msg =~ s/\n$//;
340 $self->error ("login failed: $msg"); 457 $self->error ("login failed: $msg");
341} 458}
342 459
460sub on_event_notify {
461 my ($self, $event, @args) = @_;
462
463 call $self, "on_${event}_event", @args;
464}
465
343=back 466=back
344 467
345=head2 EVENTS 468=head1 EVENTS/CALLBACKS
346 469
347AnyEvent::Porttracker conenctions are fully event-driven, and naturally 470AnyEvent::Porttracker connections are fully event-driven, and naturally
348there are a number of events that can occur. All these events have a name 471there are a number of events that can occur. All these events have a name
349starting with C<on_> (example: C<on_login_failure>). 472starting with C<on_> (example: C<on_login_failure>).
350 473
351Programs can catch these events in two ways: either by providing 474Programs can catch these events in two ways: either by providing
352constructor arguments with the event name as key and a coderef as value: 475constructor arguments with the event name as key and a code-ref as value:
353 476
354 my $api = new AnyEvent::Porttracker 477 my $api = new AnyEvent::Porttracker
355 host => ..., 478 host => ...,
356 user => ..., pass => ..., 479 user => ..., pass => ...,
357 on_error => sub { 480 on_error => sub {
359 warn $msg; 482 warn $msg;
360 exit 1; 483 exit 1;
361 }, 484 },
362 ; 485 ;
363 486
364Or by subclassing C<AnyEvent::Porttracker> and overriding methods of the 487Or by sub-classing C<AnyEvent::Porttracker> and overriding methods of the
365same name: 488same name:
366 489
367 package MyClass; 490 package MyClass;
368 491
369 use base AnyEvent::Porttracker; 492 use base AnyEvent::Porttracker;
417 540
418=item on_start_tls_notify $api 541=item on_start_tls_notify $api
419 542
420Called when the server wants to start TLS negotiation. This is used 543Called when the server wants to start TLS negotiation. This is used
421internally and - while it is possible to override it - should not be 544internally and - while it is possible to override it - should not be
422overriden. 545overridden.
546
547=item on_event_notify $api, $eventname, @args
548
549Called when the server broadcasts an event the API object is subscribed
550to. The default implementation (which should not be overridden) simply
551re-issues an "on_eventname_event" event with the @args.
423 552
424=item on_XYZ_notify $api, ... 553=item on_XYZ_notify $api, ...
425 554
426In general, any protocol notification will result in an event of the form 555In general, any protocol notification will result in an event of the form
427C<on_NOTIFICATION_notify>. 556C<on_NOTIFICATION_notify>.
428 557
558=item on_XYZ_event $api, ...
559
560Called when the server broadcasts the named (XYZ) event.
561
429=back 562=back
430 563
431=head1 SEE ALSO 564=head1 SEE ALSO
432 565
433L<AnyEvent>, L<http://www.porttracker.com/>, L<http://www.infoblox.com/en/products/portiq.html>. 566L<AnyEvent>, L<http://www.porttracker.com/>, L<http://www.infoblox.com/en/products/portiq.html>.

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines