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

Comparing AnyEvent-FastPing/FastPing.xs (file contents):
Revision 1.7 by root, Sun Jan 16 17:05:32 2011 UTC vs.
Revision 1.8 by root, Sat Jan 29 23:36:49 2011 UTC

1#if defined(__linux) 1#if defined(__linux) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__CYGWIN__)
2# define ENABLE_IPV6 1 // if you get compilation problems try to disable IPv6 2# define ENABLE_IPV6 1 // if you get compilation problems try to disable IPv6
3#else 3#else
4# define ENABLE_IPV6 0 4# define ENABLE_IPV6 0
5#endif 5#endif
6 6
30#include <arpa/inet.h> 30#include <arpa/inet.h>
31 31
32#ifdef __linux 32#ifdef __linux
33# include <linux/icmp.h> 33# include <linux/icmp.h>
34#endif 34#endif
35#if ENABLE_IPV6 35#if ENABLE_IPV6 && !defined (__CYGWIN__)
36# include <netinet/icmp6.h> 36# include <netinet/icmp6.h>
37#endif 37#endif
38 38
39#define ICMP4_ECHO 8 39#define ICMP4_ECHO 8
40#define ICMP4_ECHO_REPLY 0 40#define ICMP4_ECHO_REPLY 0
47#define HDR_SIZE_IP4 20 47#define HDR_SIZE_IP4 20
48#define HDR_SIZE_IP6 48 48#define HDR_SIZE_IP6 48
49 49
50//TODO: xread/xwrite for atomicity? we currently rely on the fact that the pip buffersize divides exactly by pointer sizes 50//TODO: xread/xwrite for atomicity? we currently rely on the fact that the pip buffersize divides exactly by pointer sizes
51 51
52typedef uint8_t addr_t[16]; 52typedef uint8_t addr_tt[16];
53 53
54typedef double tstamp; 54typedef double tstamp;
55 55
56static tstamp 56static tstamp
57NOW (void) 57NOW (void)
59 struct timeval tv; 59 struct timeval tv;
60 gettimeofday (&tv, 0); 60 gettimeofday (&tv, 0);
61 return tv.tv_sec + tv.tv_usec * 0.000001; 61 return tv.tv_sec + tv.tv_usec * 0.000001;
62} 62}
63 63
64typedef struct { 64typedef struct
65{
65 int family; 66 int family;
66 addr_t lo, hi; 67 addr_tt lo, hi;
67 double interval; 68 double interval;
68 tstamp next; 69 tstamp next;
69} RANGE; 70} RANGE;
70 71
71typedef struct { 72typedef struct
73{
72 SV *id; 74 SV *id;
73 double interval; 75 double interval;
74 int nranges; 76 int nranges;
75 RANGE *ranges; 77 RANGE *ranges;
76 uint32_t payload; 78 uint32_t payload;
77} REQ; 79} REQ;
78 80
79typedef struct { 81typedef struct
82{
80 uint8_t version_ihl; 83 uint8_t version_ihl;
81 uint8_t tos; 84 uint8_t tos;
82 uint16_t tot_len; 85 uint16_t tot_len;
83 86
84 uint16_t id; 87 uint16_t id;
90 93
91 uint32_t src; 94 uint32_t src;
92 uint32_t dst; 95 uint32_t dst;
93} IP4HDR; 96} IP4HDR;
94 97
95typedef struct { 98typedef struct
99{
96 uint8_t version; 100 uint8_t version;
97 uint8_t x1, x2, x3; 101 uint8_t x1, x2, x3;
98 102
99 uint16_t payload_len; 103 uint16_t payload_len;
100 uint8_t nxt_hdr; 104 uint8_t nxt_hdr;
106 110
107#define MAGIC 0xca4c 111#define MAGIC 0xca4c
108 112
109static uint16_t magic; 113static uint16_t magic;
110 114
111typedef struct { 115typedef struct
116{
112 uint8_t type, code; 117 uint8_t type, code;
113 uint16_t cksum; 118 uint16_t cksum;
114 uint16_t id, seq; 119 uint16_t id, seq;
115 uint32_t payload; 120 uint32_t payload;
116 tstamp stamp; // be careful when accessing this 121 tstamp stamp; // be careful when accessing this
140 145
141 return ~sum; 146 return ~sum;
142} 147}
143 148
144static void 149static void
145inc_addr (addr_t *addr) 150inc_addr (addr_tt *addr)
146{ 151{
147 int len = sizeof (addr_t) - 1; 152 int len = sizeof (addr_tt) - 1;
148 153
149 do 154 do
150 { 155 {
151 if ((*addr)[len] != 0xff) 156 if ((*addr)[len] != 0xff)
152 { 157 {
211 while (req->nranges) 216 while (req->nranges)
212 { 217 {
213 RANGE *range = req->ranges; 218 RANGE *range = req->ranges;
214 int n, k; 219 int n, k;
215 220
216 if (!memcmp (&range->lo, &range->hi, sizeof (addr_t))) 221 if (!memcmp (&range->lo, &range->hi, sizeof (addr_tt)))
217 req->ranges [0] = req->ranges [--req->nranges]; 222 req->ranges [0] = req->ranges [--req->nranges];
218 else 223 else
219 { 224 {
220 // ranges [0] is always the next range to ping 225 // ranges [0] is always the next range to ping
221 tstamp wait = range->next - now; 226 tstamp wait = range->next - now;
249 { 254 {
250 pkt.type = ICMP4_ECHO; 255 pkt.type = ICMP4_ECHO;
251 pkt.cksum = icmp_cksum (&pkt, sizeof (pkt)); 256 pkt.cksum = icmp_cksum (&pkt, sizeof (pkt));
252 257
253 memcpy (&sa4.sin_addr, 258 memcpy (&sa4.sin_addr,
254 sizeof (addr_t) - sizeof (sa4.sin_addr) + (char *)&range->lo, 259 sizeof (addr_tt) - sizeof (sa4.sin_addr) + (char *)&range->lo,
255 sizeof (sa4.sin_addr)); 260 sizeof (sa4.sin_addr));
256 261
257 if (sendto (icmp4_fd, &pkt, sizeof (pkt), 0, (struct sockaddr *)&sa4, sizeof (sa4)) > 0) 262 if (sendto (icmp4_fd, &pkt, sizeof (pkt), 0, (struct sockaddr *)&sa4, sizeof (sa4)) > 0)
258 errno = 0; 263 errno = 0;
259 } 264 }
261 { 266 {
262#if ENABLE_IPV6 267#if ENABLE_IPV6
263 pkt.type = ICMP6_ECHO; 268 pkt.type = ICMP6_ECHO;
264 269
265 memcpy (&sa6.sin6_addr, 270 memcpy (&sa6.sin6_addr,
266 sizeof (addr_t) - sizeof (sa6.sin6_addr) + (char *)&range->lo, 271 sizeof (addr_tt) - sizeof (sa6.sin6_addr) + (char *)&range->lo,
267 sizeof (sa6.sin6_addr)); 272 sizeof (sa6.sin6_addr));
268 273
269 if (sendto (icmp6_fd, &pkt, sizeof (pkt), 0, (struct sockaddr *)&sa6, sizeof (sa6)) > 0) 274 if (sendto (icmp6_fd, &pkt, sizeof (pkt), 0, (struct sockaddr *)&sa6, sizeof (sa6)) > 0)
270 errno = 0; 275 errno = 0;
271#endif 276#endif
469 hi = *av_fetch (av, 1, 1); 474 hi = *av_fetch (av, 1, 1);
470 475
471 sv_utf8_downgrade (lo, 0); 476 sv_utf8_downgrade (lo, 0);
472 sv_utf8_downgrade (hi, 0); 477 sv_utf8_downgrade (hi, 0);
473 478
474 memset (&r->lo, 0, sizeof (addr_t)); 479 memset (&r->lo, 0, sizeof (addr_tt));
475 memset (&r->hi, 0, sizeof (addr_t)); 480 memset (&r->hi, 0, sizeof (addr_tt));
476 481
477 if (SvPOKp (lo) && SvPOKp (hi)) 482 if (SvPOKp (lo) && SvPOKp (hi))
478 { 483 {
479 if (SvCUR (lo) != SvCUR (hi)) 484 if (SvCUR (lo) != SvCUR (hi))
480 croak ("all addresses in range must be of the same size (either 4 or 16 bytes)"); 485 croak ("all addresses in range must be of the same size (either 4 or 16 bytes)");
481 486
482 if (SvCUR (lo) == 4) 487 if (SvCUR (lo) == 4)
483 { 488 {
484 r->family = AF_INET; 489 r->family = AF_INET;
485 memcpy (sizeof (addr_t) - 4 + (char *)&r->lo, SvPVX (lo), 4); 490 memcpy (sizeof (addr_tt) - 4 + (char *)&r->lo, SvPVX (lo), 4);
486 memcpy (sizeof (addr_t) - 4 + (char *)&r->hi, SvPVX (hi), 4); 491 memcpy (sizeof (addr_tt) - 4 + (char *)&r->hi, SvPVX (hi), 4);
487 } 492 }
488 else if (SvCUR (lo) == 16) 493 else if (SvCUR (lo) == 16)
489 { 494 {
490#if ENABLE_IPV6 495#if ENABLE_IPV6
491 r->family = AF_INET6; 496 r->family = AF_INET6;
492 memcpy (&r->lo, SvPVX (lo), sizeof (addr_t)); 497 memcpy (&r->lo, SvPVX (lo), sizeof (addr_tt));
493 memcpy (&r->hi, SvPVX (hi), sizeof (addr_t)); 498 memcpy (&r->hi, SvPVX (hi), sizeof (addr_tt));
494#else 499#else
495 croak ("IPv6 not supported in this configuration"); 500 croak ("IPv6 not supported in this configuration");
496#endif 501#endif
497 } 502 }
498 else 503 else
502 { 507 {
503 uint32_t addr; 508 uint32_t addr;
504 509
505 r->family = AF_INET; 510 r->family = AF_INET;
506 511
507 addr = htonl (SvUV (lo)); memcpy (sizeof (addr_t) - 4 + (char *)&r->lo, &addr, 4); 512 addr = htonl (SvUV (lo)); memcpy (sizeof (addr_tt) - 4 + (char *)&r->lo, &addr, 4);
508 addr = htonl (SvUV (hi)); memcpy (sizeof (addr_t) - 4 + (char *)&r->hi, &addr, 4); 513 addr = htonl (SvUV (hi)); memcpy (sizeof (addr_tt) - 4 + (char *)&r->hi, &addr, 4);
509 } 514 }
510 else 515 else
511 croak ("addresses in range must be strings with either 4 (IPv4) or 16 (IPv6) octets"); 516 croak ("addresses in range must be strings with either 4 (IPv4) or 16 (IPv6) octets");
512 517
513 if (r->family == AF_INET) 518 if (r->family == AF_INET)

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines