AnyEvent-FastPing
view release on metacpan or search on metacpan
FastPing.pm view on Meta::CPAN
=head1 SYNOPSIS
use AnyEvent::FastPing;
=head1 DESCRIPTION
This module was written for a single purpose only: sending ICMP ECHO
REQUEST packets as quickly as possible to a large number of hosts
(thousands to millions).
It employs a separate thread and is fully event-driven (using AnyEvent),
so you have to run an event model supported by AnyEvent to use this
module.
=head1 FUNCTIONS
=over 4
=cut
package AnyEvent::FastPing;
FastPing.pm view on Meta::CPAN
=item AnyEvent::FastPing::icmp6_pktsize
Like AnyEvent::FastPing::icmp4_pktsize, but for IPv6.
=back
=head1 THE AnyEvent::FastPing CLASS
The AnyEvent::FastPing class represents a single "pinger". A "pinger"
comes with its own thread to send packets in the background, a rate-limit
machinery and separate idle/receive callbacks.
The recommended workflow (there are others) is this: 1. create a new
AnyEvent::FastPing object 2. configure the address lists and ranges to
ping, also configure an idle callback and optionally a receive callback
3. C<start> the pinger.
When the pinger has finished pinging all the configured addresses it will
call the idle callback.
FastPing.pm view on Meta::CPAN
- you should be stingy with your pinger objects.
=cut
sub new {
_boot;
our $ICMP4_W = $ICMP4_FD >= 0 && (open $ICMP4_FH, "<&=$ICMP4_FD") && AE::io $ICMP4_FH, 0, \&_recv_icmp4;
our $ICMP6_W = $ICMP6_FD >= 0 && (open $ICMP6_FH, "<&=$ICMP6_FD") && AE::io $ICMP6_FH, 0, \&_recv_icmp6;
open $THR_RES_FH, "<&=$THR_RES_FD" or die "AnyEvent::FastPing: FATAL: cannot fdopen thread result fd";
our $THR_RES_W = AE::io $THR_RES_FH, 0, sub {
sysread $THR_RES_FH, my $buf, 8;
for my $id (unpack "S*", $buf) {
_stop_id $id;
($IDLE_CB[$id] || sub { })->();
}
};
FastPing.pm view on Meta::CPAN
If your idle callback were called instantly after all ranges were
exhausted and you destroyed the object inside (which is common), then
there would be no chance to receive some replies, as there would be no
time of the packet to travel over the network.
This can be fixed by starting a timer in the idle callback, or more simply
by selecting a suitable C<max_rtt> value, which should be the maximum time
you allow a ping packet to travel to its destination and back.
The pinger thread automatically waits for this amount of time before becoming idle.
The default is currently C<0.5> seconds, which is usually plenty.
=item $pinger->add_range ($lo, $hi[, $interval])
Ping the IPv4 (or IPv6, but see below) address range, starting at binary
address C<$lo> and ending at C<$hi> (both C<$lo> and C<$hi> will be
pinged), generating no more than one ping per C<$interval> seconds (or as
fast as possible if omitted).
FastPing.xs view on Meta::CPAN
#if defined(__linux) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__CYGWIN__)
# define ENABLE_IPV6 1 // if you get compilation problems try to disable IPv6
#else
# define ENABLE_IPV6 0
#endif
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <poll.h>
#include <unistd.h>
#include <inttypes.h>
#include <fcntl.h>
FastPing.xs view on Meta::CPAN
#define ICMP4_ECHO_REPLY 0
#define ICMP6_ECHO 128
#define ICMP6_ECHO_REPLY 129
#define DRAIN_INTERVAL 1e-6 // how long to wait when sendto returns ENOBUFS, in seconds
#define MIN_INTERVAL 1e-6 // minimum packet send interval, in seconds
#define HDR_SIZE_IP4 20
#define HDR_SIZE_IP6 48
static int thr_res[2]; // worker thread finished status
static int icmp4_fd = -1;
static int icmp6_fd = -1;
/*****************************************************************************/
typedef double tstamp;
static tstamp
NOW (void)
{
FastPing.xs view on Meta::CPAN
uint16_t magic1;
uint16_t magic2;
uint16_t magic3;
int id;
AV *recvq; /* receive queue */
int nextrecv;
SV *recvcb;
pthread_t thrid;
int running;
} PINGER;
static PINGER **pingers;
static int *pingerfree; /* freelist next */
static int pingercnt;
static int pingermax;
static int firstfree = -1;
static int firstrecv = -1;
FastPing.xs view on Meta::CPAN
/* NetBSD, Solaris... */
#ifndef PTHREAD_STACK_MIN
# define PTHREAD_STACK_MIN 0
#endif
static void
pinger_start (PINGER *self)
{
sigset_t fullsigset, oldsigset;
pthread_attr_t attr;
if (self->running)
return;
sigfillset (&fullsigset);
pthread_attr_init (&attr);
pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN < sizeof (long) * 2048 ? sizeof (long) * 2048 : PTHREAD_STACK_MIN);
pthread_sigmask (SIG_SETMASK, &fullsigset, &oldsigset);
if (pthread_create (&self->thrid, &attr, ping_proc, (void *)self))
croak ("AnyEvent::FastPing: unable to create pinger thread");
pthread_sigmask (SIG_SETMASK, &oldsigset, 0);
self->running = 1;
}
static void
pinger_stop (PINGER *self)
{
if (!self->running)
return;
self->running = 0;
pthread_cancel (self->thrid);
pthread_join (self->thrid, 0);
}
static void
pinger_init (PINGER *self)
{
memset (self, 0, sizeof (PINGER));
if (firstfree >= 0)
{
self->id = firstfree;
Makefile.PL view on Meta::CPAN
PREOP => 'pod2text FastPing.pm | tee README >$(DISTVNAME)/README; chmod -R u=rwX,go=rX . ;',
COMPRESS => 'gzip -9v',
SUFFIX => '.gz',
},
PREREQ_PM => {
AnyEvent => 0,
common::sense => 3.4,
},
NAME => "AnyEvent::FastPing",
VERSION_FROM => "FastPing.pm",
LIBS => ["-lpthread -lm"],
EXE_FILES => ["bin/fastping"],
);
AnyEvent::FastPing - quickly ping a large number of hosts
SYNOPSIS
use AnyEvent::FastPing;
DESCRIPTION
This module was written for a single purpose only: sending ICMP ECHO
REQUEST packets as quickly as possible to a large number of hosts
(thousands to millions).
It employs a separate thread and is fully event-driven (using AnyEvent),
so you have to run an event model supported by AnyEvent to use this
module.
FUNCTIONS
AnyEvent::FastPing::ipv4_supported
Returns true iff IPv4 is supported in this module and on this
system.
AnyEvent::FastPing::ipv6_supported
Returns true iff IPv6 is supported in this module and on this
my $packets_per_second = $kilobit_per_second
* (1000 / 8 / AnyEvent::FastPing::icmp4_pktsize);
etc.
AnyEvent::FastPing::icmp6_pktsize
Like AnyEvent::FastPing::icmp4_pktsize, but for IPv6.
THE AnyEvent::FastPing CLASS
The AnyEvent::FastPing class represents a single "pinger". A "pinger"
comes with its own thread to send packets in the background, a
rate-limit machinery and separate idle/receive callbacks.
The recommended workflow (there are others) is this: 1. create a new
AnyEvent::FastPing object 2. configure the address lists and ranges to
ping, also configure an idle callback and optionally a receive callback
3. "start" the pinger.
When the pinger has finished pinging all the configured addresses it
will call the idle callback.
If your idle callback were called instantly after all ranges were
exhausted and you destroyed the object inside (which is common),
then there would be no chance to receive some replies, as there
would be no time of the packet to travel over the network.
This can be fixed by starting a timer in the idle callback, or more
simply by selecting a suitable "max_rtt" value, which should be the
maximum time you allow a ping packet to travel to its destination
and back.
The pinger thread automatically waits for this amount of time before
becoming idle.
The default is currently 0.5 seconds, which is usually plenty.
$pinger->add_range ($lo, $hi[, $interval])
Ping the IPv4 (or IPv6, but see below) address range, starting at
binary address $lo and ending at $hi (both $lo and $hi will be
pinged), generating no more than one ping per $interval seconds (or
as fast as possible if omitted).
( run in 0.280 second using v1.01-cache-2.11-cpan-3cd7ad12f66 )