AnyEvent-Porttracker
view release on metacpan or search on metacpan
Porttracker.pm view on Meta::CPAN
In addition to Porttracker, the PortIQ product is also supported, as it
uses the same protocol.
If you do not have access to either a Porttracker or PortIQ box then this
module will be of little value to you.
This module is an L<AnyEvent> user, you need to make sure that you use and
run a supported event loop.
To quickly understand how this module works you should read how to
construct a new connection object and then read about the event/callback
system.
The actual low-level protocol and, more importantly, the existing
requests and responses, are documented in the official Porttracker
API documentation (a copy of which is included in this module as
L<AnyEvent::Porttracker::protocol>.
=head1 THE AnyEvent::Porttracker CLASS
The AnyEvent::Porttracker class represents a single connection.
=over 4
=cut
package AnyEvent::Porttracker;
use common::sense;
use Carp ();
use Scalar::Util ();
use AnyEvent ();
use AnyEvent::Handle ();
use MIME::Base64 ();
use Digest::HMAC_MD6 ();
use JSON ();
our $VERSION = '1.01';
sub call {
my ($self, $type, @args) = @_;
$self->{$type}
? $self->{$type}($self, @args)
: ($type = (UNIVERSAL::can $self, $type))
? $type->($self, @args)
: ()
}
=item $api = new AnyEvent::Porttracker [key => value...]
Creates a new porttracker API connection object and tries to connect to
the specified host (see below). After the connection has been established,
the TLS handshake (if requested) will take place, followed by a login
attempt using either the C<none>, C<login_cram_md6> or C<login> methods,
in this order of preference (typically, C<login_cram_md6> is used, which
shields against some man-in-the-middle attacks and avoids transferring the
password).
It is permissible to send requests immediately after creating the object -
they will be queued until after successful login.
Possible key-value pairs are:
=over 4
=item host => $hostname [MANDATORY]
The hostname or IP address of the Porttracker box.
=item port => $service
The service (port) to use (default: C<porttracker=55>).
=item user => $string, pass => $string
These are the username and password to use when authentication is required
(which it is in almost all cases, so these keys are normally mandatory).
=item tls => $bool
Enables or disables TLS (default: disables). When enabled, then the
connection will try to handshake a TLS connection before logging in. If
unsuccessful a fatal error will be raised.
Since most Porttracker/PortIQ boxes will not have a sensible/verifiable
certificate, no attempt at verifying it will be done (which means
man-in-the-middle-attacks will be trivial). If you want some form of
verification you need to provide your own C<tls_ctx> object with C<<
verify => 1, verify_peername => [1, 1, 1] >> or whatever verification mode
you wish to use.
=item tls_ctx => $tls_ctx
The L<AnyEvent::TLS> object to use. See C<tls>, above.
=item on_XYZ => $coderef
You can specify event callbacks either by sub-classing and overriding the
respective methods or by specifying code-refs as key-value pairs when
constructing the object. You add or remove event handlers at any time with
the C<event> method.
=back
=cut
sub new {
my $class = shift;
my $self = bless {
id => "a",
ids => [],
queue => [], # initially queue everything
@_,
}, $class;
{
Scalar::Util::weaken (my $self = $self);
$self->{hdl} = new AnyEvent::Handle
connect => [$self->{host}, $self->{port} || "porttracker=55"],
on_error => sub {
$self->error ($_[2]);
},
on_connect => sub {
if ($self->{tls}) {
$self->_req (start_tls => sub {
$_[1]
or return $self->error ("TLS rejected by server");
$self->_login;
});
}
},
on_read => sub {
while ($_[0]{rbuf} =~ s/^([^\x0a]*)\x0a//) {
( run in 3.697 seconds using v1.01-cache-2.11-cpan-df04353d9ac )