AnyEvent-FastPing
view release on metacpan or search on metacpan
FastPing.xs view on Meta::CPAN
pkt = (PKT *)(buf + hdrlen);
if (pkt->type != ICMP4_ECHO_REPLY
|| pkt->pinger >= pingercnt
|| !pingers [pkt->pinger])
continue;
pinger = pingers [pkt->pinger];
if (!pkt_is_valid_for (pkt, pinger))
continue;
recv_feed (pinger, &sa.sin_addr, 4, NOW () - pkt_to_ts (pkt));
}
recv_flush ();
}
void
_recv_icmp6 (...)
CODE:
{
struct sockaddr_in6 sa;
PKT pkt;
int maxrecv;
for (maxrecv = 256+1; --maxrecv; )
{
PINGER *pinger;
socklen_t sl = sizeof (sa);
int len = recvfrom (icmp6_fd, &pkt, sizeof (pkt), MSG_TRUNC, (struct sockaddr *)&sa, &sl);
if (len != sizeof (PKT))
break;
if (pkt.type != ICMP6_ECHO_REPLY
|| pkt.pinger >= pingercnt
|| !pingers [pkt.pinger])
continue;
pinger = pingers [pkt.pinger];
if (!pkt_is_valid_for (&pkt, pinger))
continue;
recv_feed (pinger, &sa.sin6_addr, 16, NOW () - pkt_to_ts (&pkt));
}
recv_flush ();
}
void
_new (SV *klass, UV magic1, UV magic2, UV magic3)
PPCODE:
{
SV *pv = NEWSV (0, sizeof (PINGER));
PINGER *self = (PINGER *)SvPVX (pv);
SvPOK_only (pv);
XPUSHs (sv_2mortal (sv_bless (newRV_noinc (pv), gv_stashpv (SvPVutf8_nolen (klass), 1))));
pinger_init (self);
self->magic1 = magic1;
self->magic2 = magic2;
self->magic3 = magic3;
}
void
_free (PINGER *self)
CODE:
pinger_free (self);
IV
id (PINGER *self, ...)
CODE:
RETVAL = self->id;
OUTPUT:
RETVAL
void pinger_start (PINGER *self)
void pinger_stop (PINGER *self)
void
_stop_id (UV id)
CODE:
if (id < pingercnt && pingers [id])
pinger_stop (pingers [id]);
void
interval (PINGER *self, NV interval)
CODE:
NOT_RUNNING;
self->interval = interval > MIN_INTERVAL ? interval : MIN_INTERVAL;
void
max_rtt (PINGER *self, NV maxrtt)
CODE:
NOT_RUNNING;
self->maxrtt = maxrtt;
void
on_recv (PINGER *self, SV *cb)
CODE:
SvREFCNT_dec (self->recvcb);
self->recvcb = newSVsv (cb);
void
add_range (PINGER *self, SV *lo_, SV *hi_, NV interval = 0)
CODE:
{
STRLEN lo_len, hi_len;
char *lo = SvPVbyte (lo_, lo_len);
char *hi = SvPVbyte (hi_, hi_len);
RANGE *range;
NOT_RUNNING;
if (lo_len != hi_len || (lo_len != 4 && lo_len != 16))
croak ("AnyEvent::FastPing::add_range address range must be specified as two binary IPv4 or IPv6 addresses");
if (lo_len == 4 && icmp4_fd < 0) croak ("IPv4 support unavailable");
if (lo_len == 16 && icmp6_fd < 0) croak ("IPv6 support unavailable");
if (memcmp (lo, hi, lo_len) > 0)
croak ("AnyEvent::FastPing::add_range called with lo > hi");
range = calloc (1, sizeof (RANGE));
range->next = 0;
range->interval = interval > MIN_INTERVAL ? interval : MIN_INTERVAL;
range->addrlen = lo_len;
memcpy (sizeof (addr_tt) - lo_len + (char *)&range->lo, lo, lo_len);
memcpy (sizeof (addr_tt) - lo_len + (char *)&range->hi, hi, lo_len);
pinger_add_range (self, range);
}
void
add_hosts (PINGER *self, SV *addrs, NV interval = 0, UV interleave = 1)
CODE:
{
AV *av;
int i, j, k;
int cnt;
int addrlen = 0;
RANGE *range;
NOT_RUNNING;
if (!SvROK (addrs) || SvTYPE (SvRV (addrs)) != SVt_PVAV)
croak ("AnyEvent::FastPing::add_hosts expects an arrayref with binary IPv4 or IPv6 addresses");
av = (AV *)SvRV (addrs);
cnt = av_len (av) + 1;
for (i = 0; i < cnt; ++i)
{
SV *sv = *av_fetch (av, i, 1);
sv_utf8_downgrade (sv, 0);
j = SvCUR (sv);
if (j != 4 && j != 16)
croak ("AnyEvent::FastPing::add_hosts addresses must be specified as binary IPv4 or IPv6 addresses");
if (j > addrlen)
addrlen = j;
}
if (!cnt)
XSRETURN_EMPTY;
range = calloc (1, sizeof (RANGE) + cnt * addrlen);
range->next = 0;
range->interval = interval > MIN_INTERVAL ? interval : MIN_INTERVAL;
range->addrlen = addrlen;
range->addrcnt = cnt;
if (interleave == 0)
interleave = cnt <= 256 * 256 ? 256 : (int)sqrtf (cnt);
k = cnt;
for (j = 0; j < interleave; ++j)
for (i = j; i < cnt; i += interleave)
{
uint8_t *dst = (uint8_t *)(range + 1) + --k * addrlen;
char *pv;
STRLEN pvlen;
SV *sv = *av_fetch (av, i, 1);
sv_utf8_downgrade (sv, 0);
pv = SvPVbyte (sv, pvlen);
if (pvlen != addrlen)
{
dst [ 0] = 0x00; dst [ 1] = 0x00; dst [ 2] = 0x00; dst [ 3] = 0x00;
dst [ 4] = 0x00; dst [ 5] = 0x00; dst [ 6] = 0x00; dst [ 7] = 0x00;
dst [ 8] = 0x00; dst [ 9] = 0x00; dst [10] = 0xff; dst [11] = 0xff;
dst [12] = pv [0]; dst [13] = pv [1]; dst [14] = pv [2]; dst [15] = pv [3];
}
else
memcpy (dst, pv, addrlen);
}
pinger_add_range (self, range);
}
( run in 1.035 second using v1.01-cache-2.11-cpan-e1769b4cff6 )