File Coverage

blib/lib/Net/SNMP/QueryEngine/AnyEvent.pm
Criterion Covered Total %
statement 42 84 50.0
branch 0 10 0.0
condition 0 9 0.0
subroutine 14 23 60.8
pod 7 9 77.7
total 63 135 46.6


line stmt bran cond sub pod time code
1             package Net::SNMP::QueryEngine::AnyEvent;
2              
3 1     1   25495 use 5.006;
  1         6  
  1         56  
4 1     1   6 use strict;
  1         2  
  1         36  
5 1     1   7 use warnings;
  1         12  
  1         48  
6              
7             our $VERSION = '0.04';
8              
9 1     1   1453 use AnyEvent::Handle;
  1         33715  
  1         50  
10 1     1   13 use base 'AnyEvent::Handle';
  1         2  
  1         308  
11 1     1   1100 use Data::MessagePack;
  1         1428  
  1         29  
12 1     1   821 use Data::MessagePack::Stream;
  1         679  
  1         36  
13              
14 1     1   7 use constant RT_SETOPT => 1;
  1         3  
  1         68  
15 1     1   5 use constant RT_INFO => 3;
  1         2  
  1         43  
16 1     1   5 use constant RT_GET => 4;
  1         3  
  1         39  
17 1     1   5 use constant RT_GETTABLE => 5;
  1         2  
  1         44  
18 1     1   5 use constant RT_DEST_INFO => 6;
  1         1  
  1         39  
19 1     1   5 use constant RT_REPLY => 0x10;
  1         2  
  1         61  
20 1     1   23 use constant RT_ERROR => 0x20;
  1         2  
  1         983  
21              
22             sub read_handle;
23              
24             sub new
25             {
26 0     0 1   my $class_or_ref = shift;
27 0           my %args = (connect => ["127.0.0.1", 7667], @_, on_read => \&read_handler);
28 0           my $self = $class_or_ref->SUPER::new(%args);
29 0           $self->{sqe}{condvar} = AnyEvent->condvar;
30 0           $self->{sqe}{pending} = 0;
31 0           $self->{sqe}{mp} = Data::MessagePack->new->prefer_integer;
32 0           $self->{sqe}{up} = Data::MessagePack::Stream->new;
33 0           $self->{sqe}{cid} = int rand 1000000;
34 0           $self->{sqe}{cb} = {};
35 0           return $self;
36             }
37              
38             sub wait
39             {
40 0     0 1   my $self = shift;
41 0 0         return unless $self->{sqe}{pending};
42 0           $self->{sqe}{condvar}->recv;
43             }
44              
45             sub cmd
46             {
47 0     0 0   my ($self, $cb, @cmd) = @_;
48 0           $self->{sqe}{cb}{$self->{sqe}{cid}} = $cb;
49 0           $self->{sqe}{pending}++;
50 0 0 0       if ($self->{sqe}{pending} == 1 && $self->{sqe}{condvar}->ready) {
51             # XXX "reset" a condvar so "wait" can be correctly called again
52 0           $self->{sqe}{condvar} = AnyEvent->condvar;
53             }
54 0           $self->push_write($self->{sqe}{mp}->pack(\@cmd));
55             }
56              
57             sub read_handler
58             {
59 0     0 0   my $self = shift;
60              
61 0           $self->{sqe}{up}->feed($self->{rbuf});
62 0           $self->{rbuf} = "";
63              
64 0           while ($self->{sqe}{up}->next) {
65 0           my $data = $self->{sqe}{up}->data;
66              
67 0 0 0       if (ref($data) ne "ARRAY" || @$data < 3 || !$self->{sqe}{cb}{$data->[1]}) {
      0        
68             } else {
69 0           $self->{sqe}{cb}{$data->[1]}->($self, $data->[0] & RT_REPLY, $data->[2]);
70 0           delete $self->{sqe}{cb}{$data->[1]};
71 0           $self->{sqe}{pending}--;
72 0 0         if ($self->{sqe}{pending} <= 0) {
73 0           $self->{sqe}{condvar}->send;
74             }
75             }
76             }
77             }
78              
79             sub setopt
80             {
81 0     0 1   my ($self, $host, $port, $opts, $cb) = @_;
82 0           $self->cmd($cb, RT_SETOPT, ++$self->{sqe}{cid}, $host, $port, $opts);
83             }
84              
85             sub get
86             {
87 0     0 1   my ($self, $host, $port, $oids, $cb) = @_;
88 0           $self->cmd($cb, RT_GET, ++$self->{sqe}{cid}, $host, $port, $oids);
89             }
90              
91             sub gettable
92             {
93 0     0 1   my ($self, $host, $port, $oid, $max_rep, $cb) = @_;
94 0 0         if ($cb) {
95 0           $self->cmd($cb, RT_GETTABLE, ++$self->{sqe}{cid}, $host, $port, $oid, $max_rep);
96             } else {
97 0           $self->cmd($max_rep, RT_GETTABLE, ++$self->{sqe}{cid}, $host, $port, $oid);
98             }
99             }
100              
101             sub info
102             {
103 0     0 1   my ($self, $cb) = @_;
104 0           $self->cmd($cb, RT_INFO, ++$self->{sqe}{cid});
105             }
106              
107             sub dest_info
108             {
109 0     0 1   my ($self, $cb, $host, $port) = @_;
110 0           $self->cmd($cb, RT_DEST_INFO, ++$self->{sqe}{cid}, $host, $port);
111             }
112              
113             =head1 NAME
114              
115             Net::SNMP::QueryEngine::AnyEvent - multiplexing SNMP query engine client using AnyEvent
116              
117             =head1 VERSION
118              
119             Version 0.04
120              
121             =head1 SYNOPSIS
122              
123             This is an AnyEvent-flavored Perl client for snmp-query-engine,
124             a multiplexing SNMP query engine.
125              
126             use Net::SNMP::QueryEngine::AnyEvent;
127              
128             my $sqe = Net::SNMP::QueryEngine::AnyEvent->new;
129              
130             $sqe->setopt("127.0.0.1", 161, { community => "meow" }, sub {});
131              
132             $sqe->gettable("127.0.0.1", 161, "1.3.6.1.2.1.1", sub {
133             my ($h, $ok, $r) = @_;
134             for my $t (@$r) {
135             print "$t->[0] => $t->[1]\n";
136             }
137             });
138              
139             $sqe->get("127.0.0.1", 161,
140             ["1.3.6.1.2.1.1.5.0", "1.3.6.1.2.1.25.1.1.0"],
141             sub {
142             my ($h, $ok, $r) = @_;
143             print "Hostname: $r->[0][1]\n";
144             print "Uptime : $r->[1][1]\n";
145             });
146              
147             $sqe->wait;
148              
149             =head1 METHODS
150              
151             =head2 new
152              
153             Constructor. Takes the same arguments as the constructor of
154             the base class, AnyEvent::Handle::new,
155             but always overrides "on_read" callback.
156              
157             By default, connects to snmp-query-engine listening on
158             localhost, port 7667. Override this by specifying
159             a "connect" argument.
160              
161             =head2 wait
162              
163             Enters event loop until there are no unanswered queries.
164             Can be called multiple times.
165              
166             =head2 setopt
167              
168             Performs setopt request.
169              
170             =head2 getopt
171              
172             Performs getopt request.
173              
174             =head2 get
175              
176             Performs get request for arbitrary number
177             of OIDs.
178              
179             =head2 gettable
180              
181             Performs gettable request.
182              
183             =head2 info
184              
185             Performs info request.
186              
187             =head2 dest_info
188              
189             Performs dest_info request.
190              
191             =head1 AUTHOR
192              
193             Anton Berezin, C<< >>
194              
195             =head1 BUGS
196              
197             Please report any bugs or feature requests to C, or through
198             the web interface at L. I will be notified, and then you'll
199             automatically be notified of progress on your bug as I make changes.
200              
201              
202             =head1 SEE ALSO
203              
204             The snmp-query-engine daemon can be found on github
205             at L.
206              
207              
208             =head1 SUPPORT
209              
210             You can find documentation for this module with the perldoc command.
211              
212             perldoc Net::SNMP::QueryEngine::AnyEvent
213              
214              
215             You can also look for information at:
216              
217             =over 4
218              
219             =item * RT: CPAN's request tracker (report bugs here)
220              
221             L
222              
223             =item * AnnoCPAN: Annotated CPAN documentation
224              
225             L
226              
227             =item * CPAN Ratings
228              
229             L
230              
231             =item * Search CPAN
232              
233             L
234              
235             =back
236              
237              
238             =head1 ACKNOWLEDGEMENTS
239              
240             This work is in part sponsored by Telia Denmark.
241              
242             =head1 LICENSE AND COPYRIGHT
243              
244             Copyright (c) 2012-2014, Anton Berezin "". All rights
245             reserved.
246              
247             Redistribution and use in source and binary forms, with or without
248             modification, are permitted provided that the following conditions are
249             met:
250              
251             1. Redistributions of source code must retain the above copyright
252             notice, this list of conditions and the following disclaimer.
253              
254             2. Redistributions in binary form must reproduce the above copyright
255             notice, this list of conditions and the following disclaimer in the
256             documentation and/or other materials provided with the distribution.
257              
258             THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
259             EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
260             IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
261             PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE
262             LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
263             CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
264             SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
265             BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
266             WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
267             OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
268             ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
269              
270             =cut
271              
272             1;