File Coverage

blib/lib/Net/Radius/Server/DBStore.pm
Criterion Covered Total %
statement 18 93 19.3
branch 0 52 0.0
condition 0 20 0.0
subroutine 6 10 60.0
pod n/a
total 24 175 13.7


line stmt bran cond sub pod time code
1             #! /usr/bin/perl
2             #
3             #
4             # $Id: DBStore.pm 109 2009-10-17 22:00:16Z lem $
5              
6             package Net::Radius::Server::DBStore;
7              
8 1     1   1343 use 5.010;
  1         4  
  1         40  
9 1     1   5 use strict;
  1         2  
  1         24  
10 1     1   5 use warnings;
  1         1  
  1         24  
11              
12 1     1   956 use Storable qw/freeze/;
  1         4489  
  1         107  
13              
14 1     1   11 use Net::Radius::Server::Base qw/:set/;
  1         3  
  1         16  
15 1     1   70 use base 'Net::Radius::Server::Base';
  1         3  
  1         977  
16             __PACKAGE__->mk_accessors(qw/key_attrs param store result sync
17             pre_store_hook single frozen hashref
18             internal_tie/);
19             our $VERSION = do { sprintf "%0.3f", 1+(q$Revision: 109 $ =~ /\d+/g)[0]/1000 };
20              
21             sub mk
22             {
23 0     0     my $class = shift;
24 0 0 0       die "->mk() cannot have arguments when in object-method mode\n"
      0        
25             if ref($class) and $class->isa('UNIVERSAL') and @_;
26              
27 0           my $self = $class;
28              
29 0 0         if (@_)
30             {
31 0           $self = $class->new(@_);
32 0 0         die "Failed to create new object\n" unless $self;
33             }
34              
35 0 0         die "->mk() cannot proceed with no valid param defined\n"
36             unless ref($self->param) eq 'ARRAY';
37              
38             # Enforce default values
39              
40 0 0         $self->frozen(1) unless defined $self->frozen();
41 0 0         $self->single(1) unless defined $self->single();
42 0 0         $self->internal_tie(1) unless defined $self->internal_tie();
43              
44 0 0         $self->key_attrs([ 'NAS-IP-Address', '|', 'Acct-Session-Id' ])
45             unless $self->key_attrs();
46              
47 0 0         $self->store([ qw/ packet peer_addr peer_host peer_port port /])
48             unless $self->store();
49              
50 0 0         $self->sync(1)
51             unless defined $self->sync();
52            
53 0 0         $self->log_level(1)
54             unless defined $self->log_level();
55              
56             # Create the tied hash that we will be passing into the actual method.
57              
58 0           my ($db, %hash);
59 0           my ($c, @params) = (@{$self->param});
  0            
60              
61 0 0         $self->hashref(\%hash) unless $self->hashref;
62              
63 0           $self->log(2, "Tying to class '" . $c . "'");
64 0           $self->log(3, "Tie parameters are " . join(', ', @params));
65 0 0         if ($self->internal_tie)
66             {
67 0           eval { $db = tie %{$self->hashref}, $c, @params };
  0            
  0            
68              
69 0 0         die "->mk() unable to tie: $!" unless $db;
70 0 0         die "->mk() problem during tie: $@" if $@;
71             }
72             else
73             {
74 0           $self->log(2, "Not tying because ->internal_tie is true");
75             }
76            
77 0     0     return sub { $self->_do_tie( $db, $self->hashref, @_ ) };
  0            
78             }
79              
80             # Convert a scalar into the corresponding Radius attribute in
81             # $req. Will return non-matched scalars, to be used as delimiters in
82             # the resulting key.
83             sub _k
84             {
85 0     0     my ($self, $db, $rhash, $r_data, $req, $attr) = @_;
86 0           my $v = undef;
87              
88 0 0         if (ref($attr) eq 'ARRAY')
    0          
89             {
90 0           $v = $req->vsattr(@$attr);
91 0 0         return $v->[0] if ref($v) eq 'ARRAY';
92 0 0         return $v if defined $v;
93 0           return '';
94             }
95             elsif (ref($attr) eq 'CODE')
96             {
97 0           return $attr->($self, $db, $rhash, $r_data, $req);
98             }
99             else
100             {
101 0           $v = $req->attr($attr);
102 0 0         return $v if defined $v;
103             }
104              
105 0           return $attr;
106             }
107              
108             sub _do_tie
109             {
110 0     0     my $self = shift;
111 0           my $db = shift;
112 0           my $rhash = shift;
113 0           my $r_data = shift;
114              
115 0           my $req = $r_data->{request};
116              
117 0           $self->log(2, 'Storing data');
118 0           $self->log(4, "self=$self rhash=$rhash r_data=$r_data");
119              
120             # Find the key to store
121 0           my $key = join('', (map { $self->_k($db, $rhash, $r_data, $req, $_) }
  0            
122 0           @{$self->key_attrs}));
123 0           $self->log(4, 'Storing data using key "' . $key . '"');
124              
125             # Invoke hook, if available
126 0           my $f = undef;
127 0 0 0       if ($f = $self->pre_store_hook()
128             and ref($f) eq 'CODE')
129             {
130 0           $self->log(3, 'Invoking pre_store_hook');
131             # Note that the pre_store_hook could change object's config...
132 0           $f->($self, $db, $rhash, $r_data, $req, $key);
133             }
134             else
135             {
136 0           $self->log(4, 'no pre_store_hook');
137             }
138              
139             # Find what to store
140 0           my @store = @{$self->store};
  0            
141 0           $self->log(4, 'Storing the following items: ' . join(', ', @store));
142 0           my %data = map { $_ => $r_data->{$_} } @store;
  0            
143              
144 0 0         if ($self->single)
145             {
146 0           $self->log(4, "Single Store $key: ", \%data);
147 0 0         $rhash->{$key} = ($self->frozen ? freeze \%data : \%data);
148             }
149             else
150             {
151 0           while (my ($k, $v) = each %data)
152             {
153 0           $self->log(4, "Non-Single Store $key->$k: $v");
154 0 0         $rhash->{$key}->{$k} = ($self->frozen ? freeze $v : $v)
155             }
156             }
157 0   0       $self->log(4, "tuple contains: " . $rhash->{$key} // 'undef');
158              
159             # Force sync writes
160 0 0 0       $db->db_sync if $db and $self->sync and $db->can('db_sync');
      0        
161              
162 0 0 0       if ($self->can('result') and exists $self->{result})
163             {
164 0           my $r = $self->result;
165 0           $self->log(3, "Returning $r");
166 0           return $r;
167             }
168              
169 0           $self->log(3, "Returning CONTINUE by default");
170 0           return NRS_SET_CONTINUE;
171             }
172              
173             42;
174              
175             __END__