AnyEvent-Radius
view release on metacpan or search on metacpan
lib/AnyEvent/Radius/Client.pm view on Meta::CPAN
package AnyEvent::Radius::Client;
# AnyEvent-based radius client
use strict;
use warnings;
use AnyEvent;
use AnyEvent::Handle::UDP;
use base qw(Class::Accessor::Fast);
__PACKAGE__->mk_accessors(qw(
handler packer send_cache
queue_cv write_cv read_cv
sent_cnt reply_cnt queue_cnt
last_request_id
));
use Data::Radius v1.2.8;
use Data::Radius::Constants qw(%RADIUS_PACKET_TYPES);
use Data::Radius::Dictionary ();
use Data::Radius::Packet ();
use constant {
READ_TIMEOUT_SEC => 5,
WRITE_TIMEOUT_SEC => 5,
RADIUS_PORT => 1812,
MAX_REQUEST_ID => 0xFF,
};
# deprecated?
use constant MAX_QUEUE => MAX_REQUEST_ID() + 1;
# new 'NAS'
# args:
# ip
# port
# secret
# dictionary
# read_timeout
# write_timeout
# bind_ip
# initial_last_request_id - random by default
#- callbacks:
# on_read
# on_read_raw
# on_read_timeout
# on_write_timeout
# on_error
sub new {
my ($class, %h) = @_;
my $obj = bless {}, $class;
# either pre-created packer object, or need radius secret to create new one
# dictionary is optional
if ( defined $h{packer} ) {
$obj->packer( $h{packer} );
} elsif ( defined $h{secret} ) {
$obj->packer( Data::Radius::Packet->new(dict => $h{dictionary}, secret => $h{secret}) );
} else {
die "No radius secret";
}
my %udp_handle_args = (
rtimeout => $h{read_timeout} // READ_TIMEOUT_SEC,
wtimeout => $h{write_timeout} // WRITE_TIMEOUT_SEC,
);
die "No IP argument" if ! exists $h{ip};
$udp_handle_args{connect} = [ $h{ip}, $h{port} // RADIUS_PORT ];
$udp_handle_args{bind} = [$h{bind_ip}, 0] if exists $h{bind_ip};
$udp_handle_args{on_recv} = sub {
my ($data, $handle, $from) = @_;
$obj->read_cv->end;
$obj->reply_cnt($obj->reply_cnt + 1);
if ($h{on_read_raw}) {
# dump raw data
$h{on_read_raw}->($obj, $data, $from);
}
# using authenticator from request to verify reply
my $request_id = $obj->packer()->request_id($data);
# FIXME how to react on unknown request_id ?
my $send_info = delete $obj->send_cache()->{ $request_id };
if (! $send_info ) {
# got unknown reply (with wrong request id?)
if ($h{on_error}) {
$h{on_error}->($obj, 'Unknown reply');
}
else {
warn "Error: unknown reply";
}
}
else {
my $on_read = $h{on_read};
my $req_callback = $send_info->{callback};
if ( $on_read || $req_callback ) {
# how to decode $from
# my($port, $host) = AnyEvent::Socket::unpack_sockaddr($from);
# my $ip = format_ipv4($host);
( run in 1.903 second using v1.01-cache-2.11-cpan-140bd7fdf52 )