File Coverage

blib/lib/AnyEvent/FastPing.pm
Criterion Covered Total %
statement 26 26 100.0
branch 1 2 50.0
condition 3 8 37.5
subroutine 8 8 100.0
pod 2 2 100.0
total 40 46 86.9


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             AnyEvent::FastPing - quickly ping a large number of hosts
4              
5             =head1 SYNOPSIS
6              
7             use AnyEvent::FastPing;
8              
9             =head1 DESCRIPTION
10              
11             This module was written for a single purpose only: sending ICMP ECHO
12             REQUEST packets as quickly as possible to a large number of hosts
13             (thousands to millions).
14              
15             It employs a separate thread and is fully event-driven (using AnyEvent),
16             so you have to run an event model supported by AnyEvent to use this
17             module.
18              
19             =head1 FUNCTIONS
20              
21             =over 4
22              
23             =cut
24              
25             package AnyEvent::FastPing;
26              
27 2     2   13336 use common::sense;
  2         21  
  2         12  
28              
29 2     2   1608 use AnyEvent;
  2         5937  
  2         275  
30              
31             BEGIN {
32 2     2   5 our $VERSION = 2.1;
33 2         28 our @ISA = qw(Exporter);
34              
35 2         14 require Exporter;
36             #Exporter::export_ok_tags (keys %EXPORT_TAGS);
37              
38 2         6 require XSLoader;
39 2         3184 XSLoader::load (__PACKAGE__, $VERSION);
40             }
41              
42             our ($THR_RES_FD, $ICMP4_FD, $ICMP6_FD);
43              
44             our $THR_RES_FH;
45              
46             our $ICMP4_FH;
47             our $ICMP6_FH;
48              
49             our @IDLE_CB;
50              
51             =item AnyEvent::FastPing::ipv4_supported
52              
53             Returns true iff IPv4 is supported in this module and on this system.
54              
55             =item AnyEvent::FastPing::ipv6_supported
56              
57             Returns true iff IPv6 is supported in this module and on this system.
58              
59             =item AnyEvent::FastPing::icmp4_pktsize
60              
61             Returns the number of octets per IPv4 ping packet (the whole IP packet
62             including headers, excluding lower-level headers or trailers such as
63             Ethernet).
64              
65             Can be used to calculate e.g. octets/s from rate ...
66              
67             my $octets_per_second = $packets_per_second * AnyEvent::FastPing::icmp4_pktsize;
68              
69             ... or convert kilobit/second to packet rate ...
70              
71             my $packets_per_second = $kilobit_per_second
72             * (1000 / 8 / AnyEvent::FastPing::icmp4_pktsize);
73              
74             etc.
75              
76             =item AnyEvent::FastPing::icmp6_pktsize
77              
78             Like AnyEvent::FastPing::icmp4_pktsize, but for IPv6.
79              
80             =back
81              
82             =head1 THE AnyEvent::FastPing CLASS
83              
84             The AnyEvent::FastPing class represents a single "pinger". A "pinger"
85             comes with its own thread to send packets in the background, a rate-limit
86             machinery and separate idle/receive callbacks.
87              
88             The recommended workflow (there are others) is this: 1. create a new
89             AnyEvent::FastPing object 2. configure the address lists and ranges to
90             ping, also configure an idle callback and optionally a receive callback
91             3. C the pinger.
92              
93             When the pinger has finished pinging all the configured addresses it will
94             call the idle callback.
95              
96             The pinging process works like this: every range has a minimum interval
97             between sends, which is used to limit the rate at which hosts in that
98             range are being pinged. Distinct ranges are independent of each other,
99             which is why there is a per-pinger "global" minimum interval as well.
100              
101             The pinger sends pings as fats as possible, while both obeying the pinger
102             rate limit as well as range limits.
103              
104             When a range is exhausted, it is removed. When all ranges are exhausted,
105             the pinger waits another C seconds and then exits, causing the
106             idle callback to trigger.
107              
108             Performance: On my 2 GHz Opteron system with a pretty average nvidia
109             gigabit network card I can ping around 60k to 200k addresses per second,
110             depending on routing decisions.
111              
112             Example: ping 10.0.0.1-10.0.0.15 with at most 100 packets/s, and
113             11.0.0.1-11.0.255.255 with at most 1000 packets/s. Also ping the IPv6
114             loopback address 5 times as fast as possible. Do not, however, exceed 1000
115             packets/s overall. Also dump each received reply.
116              
117             use AnyEvent::Socket;
118             use AnyEvent::FastPing;
119              
120             my $done = AnyEvent->condvar;
121              
122             my $pinger = new AnyEvent::FastPing;
123              
124             $pinger->interval (1/1000);
125             $pinger->max_rtt (0.1); # reasonably fast/reliable network
126              
127             $pinger->add_range (v10.0.0.1, v10.0.0.15, 1/100);
128             $pinger->add_range (v11.0.0.1, v11.0.255.255, 1/1000);
129             $pinger->add_hosts ([ (v0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1) x 5 ]);
130              
131             $pinger->on_recv (sub {
132             for (@{ $_[0] }) {
133             printf "%s %g\n", (AnyEvent::Socket::format_address $_->[0]), $_->[1];
134             }
135             });
136              
137             $pinger->on_idle (sub {
138             print "done\n";
139             undef $pinger;
140             });
141              
142             $pinger->start;
143             $done->wait;
144              
145             =head2 METHODS
146              
147             =over 4
148              
149             =item $pinger = new AnyEvent::FastPing
150              
151             Creates a new pinger - right now there can be at most C<65536> pingers in
152             a process, although that limit might change to something drastically lower
153             - you should be stingy with your pinger objects.
154              
155             =cut
156              
157             sub new {
158 1     1 1 8534 _boot;
159              
160 1   33     64 our $ICMP4_W = $ICMP4_FD >= 0 && (open $ICMP4_FH, "<&=$ICMP4_FD") && AE::io $ICMP4_FH, 0, \&_recv_icmp4;
161 1   33     41 our $ICMP6_W = $ICMP6_FD >= 0 && (open $ICMP6_FH, "<&=$ICMP6_FD") && AE::io $ICMP6_FH, 0, \&_recv_icmp6;
162              
163 1 50       36 open $THR_RES_FH, "<&=$THR_RES_FD" or die "AnyEvent::FastPing: FATAL: cannot fdopen thread result fd";
164              
165             our $THR_RES_W = AE::io $THR_RES_FH, 0, sub {
166 1     1   32819 sysread $THR_RES_FH, my $buf, 8;
167              
168 1         29 for my $id (unpack "S*", $buf) {
169 1         619 _stop_id $id;
170 1   50     26 ($IDLE_CB[$id] || sub { })->();
171             }
172 1         20 };
173              
174             *new = sub {
175 1     1   97 _new shift, (rand 65536), (rand 65536), (rand 65536)
176 1         12 };
177              
178 1         8 goto &new;
179             }
180              
181             sub DESTROY {
182 1     1   150 undef $IDLE_CB[ &id ];
183 1         0 &_free;
184             }
185              
186             =item $pinger->on_recv ($callback->([[$host, $rtt], ...]))
187              
188             Registers a callback to be called for ping replies. If no callback has
189             been registered than ping replies will be ignored, otherwise this module
190             calculates the round trip time, in seconds, for each reply and calls this
191             callback.
192              
193             The callback receives a single argument, which is an array reference
194             with an entry for each reply packet (the replies will be batched for
195             efficiency). Each member in the array reference is again an array
196             reference with exactly two members: the binary host address (4 octets for
197             IPv4, 16 for IPv6) and the approximate round trip time, in seconds.
198              
199             The replies will be passed to the callback as soon as they arrive, and
200             this callback can be called many times with batches of replies.
201              
202             The receive callback will be called whenever a suitable reply arrives,
203             whether generated by this pinger or not, whether this pinger is started
204             or not. The packets will have a unique 64 bit ID to distinguish them from
205             other pinger objects and other generators, but this doesn't help against
206             malicious replies.
207              
208             Note that very high packet rates can overwhelm your process, causing
209             replies to be dropped (configure your kernel with long receive queues for
210             raw sockets if this is a problem).
211              
212             Example: register a callback which simply dumps the received data.
213              
214             use AnyEvent::Socket;
215              
216             $pinger->on_recv (sub {
217             for (@{ $_[0] }) {
218             printf "%s %g\n", (AnyEvent::Socket::format_address $_->[0]), $_->[1];
219             }
220             });
221              
222             Example: a single ping reply with payload of 1 from C<::1> gets passed
223             like this:
224              
225             [
226             [ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1", 0.000280141830444336 ]
227             ]
228              
229             Example: ping replies for C<127.0.0.1> and C<127.0.0.2>:
230              
231             [
232             [ "\177\0\0\1", 0.00015711784362793 ],
233             [ "\177\0\0\2", 0.00090184211731 ]
234             ]
235              
236             =item $pinger->on_idle ($callback->())
237              
238             Registers a callback to be called when the pinger becomes I, that
239             is, it has been started, has exhausted all ping ranges and waited for
240             the C time. An idle pinger is also stopped, so the callback can
241             instantly add new ranges, if it so desires.
242              
243             =cut
244              
245             sub on_idle {
246 1     1 1 34 $IDLE_CB[ &id ] = $_[1];
247             }
248              
249             =item $pinger->interval ($seconds)
250              
251             Configures the minimum interval between packet sends for this pinger - the
252             pinger will not send packets faster than this rate (or actually 1 / rate),
253             even if individual ranges have a lower interval.
254              
255             A value of C<0> selects the fastest possible speed (currently no faster
256             than 1_000_000 packets/s).
257              
258             =item $pinger->max_rtt ($seconds)
259              
260             If your idle callback were called instantly after all ranges were
261             exhausted and you destroyed the object inside (which is common), then
262             there would be no chance to receive some replies, as there would be no
263             time of the packet to travel over the network.
264              
265             This can be fixed by starting a timer in the idle callback, or more simply
266             by selecting a suitable C value, which should be the maximum time
267             you allow a ping packet to travel to its destination and back.
268              
269             The pinger thread automatically waits for this amount of time before becoming idle.
270              
271             The default is currently C<0.5> seconds, which is usually plenty.
272              
273             =item $pinger->add_range ($lo, $hi[, $interval])
274              
275             Ping the IPv4 (or IPv6, but see below) address range, starting at binary
276             address C<$lo> and ending at C<$hi> (both C<$lo> and C<$hi> will be
277             pinged), generating no more than one ping per C<$interval> seconds (or as
278             fast as possible if omitted).
279              
280             You can convert IP addresses from text to binary form by
281             using C, C,
282             C or any other method that you like :)
283              
284             The algorithm to select the next address is O(log n) on the number of
285             ranges, so even a large number of ranges (many thousands) is manageable.
286              
287             No storage is allocated per address.
288              
289             Note that, while IPv6 addresses are currently supported, the usefulness of
290             this option is extremely limited and might be gone in future versions - if
291             you want to ping a number of IPv6 hosts, better specify them individually
292             using the C method.
293              
294             =item $pinger->add_hosts ([$host...], $interval, $interleave)
295              
296             Similar to C, but uses a list of single addresses instead. The
297             list is specified as an array reference as first argument. Each entry in
298             the array should be a binary host address, either IPv4 or IPv6. If all
299             addresses are IPv4 addresses, then a compact IPv4-only format will be used
300             to store the list internally.
301              
302             Minimum C<$interval> is the same as for C and can be left out.
303              
304             C<$interlave> specifies an increment between addresses: often address
305             lists are generated in a way that results in clustering - first all
306             addresses from one subnet, then from the next, and so on. To avoid this,
307             you can specify an interleave factor. If it is C<1> (the default), then
308             every address is pinged in the order specified. If it is C<2>, then only
309             every second address will be pinged in the first round, followed by a
310             second round with the others. Higher factors will create C<$interleave>
311             runs of addresses spaced C<$interleave> indices in the list.
312              
313             The special value C<0> selects a (hopefully) suitable interleave factor
314             automatically - currently C<256> for lists with less than 65536 addresses,
315             and the square root of the list length otherwise.
316              
317             =item $pinger->start
318              
319             Start the pinger, unless it is running already. While a pinger is running
320             you must not modify the pinger. If you want to change a parameter, you
321             have to C the pinger first.
322              
323             The pinger will automatically stop when destroyed.
324              
325             =item $pinger->stop
326              
327             Stop the pinger, if it is running. A pinger can be stopped at any time,
328             after which it's current state is preserved - starting it again will
329             continue where it left off.
330              
331             =cut
332              
333             1;
334              
335             =back
336              
337             =head1 AUTHOR
338              
339             Marc Lehmann
340             http://home.schmorp.de/
341              
342             =head1 LICENSE
343              
344             This software is distributed under the GENERAL PUBLIC LICENSE, version 2
345             or any later version or, at your option, the Artistic License.
346              
347             =cut
348