ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent-FastPing/FastPing.pm
(Generate patch)

Comparing AnyEvent-FastPing/FastPing.pm (file contents):
Revision 1.1 by root, Sun Apr 27 15:43:51 2008 UTC vs.
Revision 1.12 by root, Tue Feb 1 04:06:24 2011 UTC

6 6
7 use AnyEvent::FastPing; 7 use AnyEvent::FastPing;
8 8
9=head1 DESCRIPTION 9=head1 DESCRIPTION
10 10
11This module was written for a single purpose only: sending ICMP EHCO 11This module was written for a single purpose only: sending ICMP ECHO
12REQUEST packets as quickly as possible to a large number of hosts 12REQUEST packets as quickly as possible to a large number of hosts
13(thousands to millions). 13(thousands to millions).
14 14
15It employs a sending thread and is fully event-driven (using AnyEvent), so 15It employs a sending thread and is fully event-driven (using AnyEvent), so
16you have to run an event model supported by AnyEvent to use this module. 16you have to run an event model supported by AnyEvent to use this module.
21 21
22=cut 22=cut
23 23
24package AnyEvent::FastPing; 24package AnyEvent::FastPing;
25 25
26use strict; 26use common::sense;
27no warnings;
28 27
29use AnyEvent; 28use AnyEvent;
30 29
31BEGIN { 30BEGIN {
32 our $VERSION = '1.0'; 31 our $VERSION = '2.0';
33 our @ISA = qw(Exporter); 32 our @ISA = qw(Exporter);
34 33
35 require Exporter; 34 require Exporter;
36 #Exporter::export_ok_tags (keys %EXPORT_TAGS); 35 #Exporter::export_ok_tags (keys %EXPORT_TAGS);
37 36
38 require XSLoader; 37 require XSLoader;
39 XSLoader::load (__PACKAGE__, $VERSION); 38 XSLoader::load (__PACKAGE__, $VERSION);
40} 39}
41 40
42our ($THR_REQ_FD, $THR_RES_FD, $ICMP4_FD, $ICMP6_FD); 41our ($THR_RES_FD, $ICMP4_FD, $ICMP6_FD);
43 42
44our $THR_REQ_FH; open $THR_REQ_FH, ">&=$THR_REQ_FD" or die "FATAL: cannot fdopen";
45our $THR_RES_FH; open $THR_RES_FH, "<&=$THR_RES_FD" or die "FATAL: cannot fdopen"; 43our $THR_RES_FH; open $THR_RES_FH, "<&=$THR_RES_FD" or die "FATAL: cannot fdopen";
46 44
47our $THR_REQ_W; 45our $ICMP4_FH; our $ICMP4_W = $ICMP4_FD >= 0 && (open $ICMP4_FH, "<&=$ICMP4_FD") && AE::io $ICMP4_FH, 0, \&_recv_icmp4;
48our $THR_RES_W = AnyEvent->io (fh => $THR_RES_FH, poll => 'r', cb => sub { 46our $ICMP6_FH; our $ICMP6_W = $ICMP6_FD >= 0 && (open $ICMP6_FH, "<&=$ICMP6_FD") && AE::io $ICMP6_FH, 0, \&_recv_icmp6;
49 my $sv = _read_res
50 or return;
51 47
52 $sv->(); 48=item AnyEvent::FastPing::ipv4_supported
49
50Returns true if IPv4 is supported in this module and on this system.
51
52=item AnyEvent::FastPing::ipv6_supported
53
54Returns true if IPv6 is supported in this module and on this system.
55
56=item AnyEvent::FastPing::icmp4_pktsize
57
58Returns the number of bytes each IPv4 ping packet has.
59
60=item AnyEvent::FastPing::icmp6_pktsize
61
62Returns the number of bytes each IPv4 ping packet has.
63
64=cut
65
66sub new {
67 my ($klass) = @_;
68
69 _new $klass, (rand 65536), (rand 65536), (rand 65536)
70}
71
72our @IDLE_CB;
73
74sub DESTROY {
75 undef $IDLE_CB[ &id ];
76 &_free;
77}
78
79sub on_idle {
80 $IDLE_CB[ &id ] = $_[1];
81}
82
83our $THR_RES_W = AE::io $THR_RES_FH, 0, sub {
84 sysread $THR_RES_FH, my $buf, 8;
85
86 for my $id (unpack "S*", $buf) {
87 _stop_id $id;
88 ($IDLE_CB[$id] || sub { })->();
89 }
90};
91
92for(1..10) {
93my $p = new AnyEvent::FastPing;#d#
94$p->interval (0);
95$p->max_rtt (0.5);
96#$p->add_range (v127.0.0.1, v127.255.255.254, 0);
97$p->add_range (v127.0.0.1, v127.0.0.1, 0);
98#$p->add_range (v1.0.0.1, v1.255.255.254, 0);
99$p->on_idle (my $cv = AE::cv);
100my $cnt;
101$p->on_recv (sub {
102 $cnt++;
53}); 103});
104$p->start;
54 105
55our $THR_REQ_BUF; 106{
56 107 my $p = new AnyEvent::FastPing;#d#
57sub _send_req($) { 108 $p->interval (0);
58 $THR_REQ_BUF .= $_[0]; 109 $p->max_rtt (0.5);
59 110 $p->add_hosts ([v0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.2, (v0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1)x8, v0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.3], 0);
60 $THR_REQ_W ||= AnyEvent->io (fh => $THR_REQ_FH, poll => 'w', cb => sub { 111 my $cnt;
61 my $len = syswrite $THR_REQ_FH, $THR_REQ_BUF; 112 $p->on_recv (sub {
62 substr $THR_REQ_BUF, 0, $len, ""; 113 use Data::Dump; ddx \@_;
63
64 undef $THR_REQ_W unless length $THR_REQ_BUF;
65 }); 114 });
115 $p->on_idle (sub {
116 undef $p;
117 });
118 $p->start;
66} 119}
67 120
68=item AnyEvent::FastPing::ipv4_supported 121$cv->recv;
69 122warn $cnt;
70Returns true if IPv4 is supported in this module and on this system. 123}
71
72=item AnyEvent::FastPing::ipv6_supported
73
74Returns true if IPv6 is supported in this module and on this system.
75
76=item AnyEvent::FastPing::icmp4_pktsize
77
78Returns the number of bytes each IPv4 ping packet has.
79
80=item AnyEvent::FastPing::icmp6_pktsize
81
82Returns the number of bytes each IPv4 ping packet has.
83 124
84=item AnyEvent::FastPing::icmp_ping [ranges...], $send_interval, $payload, \&callback 125=item AnyEvent::FastPing::icmp_ping [ranges...], $send_interval, $payload, \&callback
85 126
86Ping the given IPv4 address ranges. Each range is an arrayref of the 127Ping the given IPv4 address ranges. Each range is an arrayref of the
87form C<[lo, hi, interval]>, where C<lo> and C<hi> are octet strings with 128form C<[lo, hi, interval]>, where C<lo> and C<hi> are octet strings with
91range C<interval> is the minimum time in seconds between pings to the 132range C<interval> is the minimum time in seconds between pings to the
92given range. If omitted, defaults to C<$send_interval>. 133given range. If omitted, defaults to C<$send_interval>.
93 134
94The C<$send_interval> is the minimum interval between sending any two 135The C<$send_interval> is the minimum interval between sending any two
95packets and is a way to make an overall rate limit. If omitted, pings will 136packets and is a way to make an overall rate limit. If omitted, pings will
96be send as fast as possible. 137be sent as fast as possible.
97 138
98The C<$payload> is a 32 bit unsigned integer given as the ICMP ECHO 139The C<$payload> is a 32 bit unsigned integer given as the ICMP ECHO
99REQUEST ident and sequence numbers (in unspecified order :). 140REQUEST ident and sequence numbers (in unspecified order :).
100 141
101The request will be queued and all requests will be served by a background 142The request will be queued and all requests will be served by a background
141 $done->wait; 182 $done->wait;
142 183
143=cut 184=cut
144 185
145sub icmp_ping($$$&) { 186sub icmp_ping($$$&) {
146 _send_req _req_icmp_ping @_; 187# _send_req _req_icmp_ping @_;
147} 188}
148
149our $ICMP4_FH;
150our $ICMP4_W = (open $ICMP4_FH, "<&=$ICMP4_FD") && AnyEvent->io (fh => $ICMP4_FH, poll => 'r', cb => \&_recv_icmp4);
151our $ICMP6_FH;
152our $ICMP6_W = (open $ICMP6_FH, "<&=$ICMP6_FD") && AnyEvent->io (fh => $ICMP6_FH, poll => 'r', cb => \&_recv_icmp6);
153 189
154=item AnyEvent::FastPing::register_cb \&cb 190=item AnyEvent::FastPing::register_cb \&cb
155 191
156Register a callback that is called for every received ping reply 192Register a callback that is called for every received ping reply
157(regardless of whether a ping is still in process or not and regardless of 193(regardless of whether a ping is still in process or not and regardless of
158whether the reply is actually a reply to a ping sent earlier). 194whether the reply is actually a reply to a ping sent earlier).
159 195
160The code reference gets a single parameter - an arrayref with an 196The code reference gets a single parameter - an arrayref with an
161entry for each received packet (replies are beign batched for greater 197entry for each received packet (replies are being batched for greater
162efficiency). Each packet is represented by an arrayref with three members: 198efficiency). Each packet is represented by an arrayref with three members:
163the source address (an octet string of either 4 (IPv4) or 16 (IPv6) octets 199the source address (an octet string of either 4 (IPv4) or 16 (IPv6) octets
164length), the payload as passed to C<icmp_ping> and the round trip time in 200length), the payload as passed to C<icmp_ping> and the round trip time in
165seconds. 201seconds.
202
203Example: register a callback which simply dumps the received data. Since
204the coderef is created on the fly via sub, it would be hard to unregister
205this callback again :)
206
207 AnyEvent::FastPing::register_cb sub {
208 for (@{$_[0]}) {
209 printf "%s %d %g\n",
210 (4 == length $_->[0] ? inet_ntoa $_->[0] : Socket6::inet_ntop (&AF_INET6, $_->[0])),
211 $_->[2],
212 $_->[1];
213 }
214 };
166 215
167Example: a single ping reply with payload of 1 from C<::1> gets passed 216Example: a single ping reply with payload of 1 from C<::1> gets passed
168like this: 217like this:
169 218
170 [ [ 219 [ [
196 245
197=cut 246=cut
198 247
199our @CB; 248our @CB;
200 249
201sub register_cb(&) { 250sub register_cb($) {
202 push @CB, $_[0]; 251 push @CB, $_[0];
203} 252}
204 253
205sub unregister_cb($) { 254sub unregister_cb($) {
206 @CB = grep $_ != $_[0], @CB; 255 @CB = grep $_ != $_[0], @CB;
210 259
211=back 260=back
212 261
213=head1 AUTHOR 262=head1 AUTHOR
214 263
215 Marc Lehmann <schmorp@schmorp.de> 264 Marc Lehmann <schmorp@schmorp.de>
216 http://home.schmorp.de/ 265 http://home.schmorp.de/
217 266
218=head1 AUTHOR 267=head1 LICENSE
219 268
220 This software is distributed under the GENERAL PUBLIC LICENSE, version 2 269 This software is distributed under the GENERAL PUBLIC LICENSE, version 2
221 or any later version or, at your option, the Artistic License. 270 or any later version or, at your option, the Artistic License.
222 271
223=cut 272=cut
224 273

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines