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

Comparing AnyEvent-FastPing/FPing.xs (file contents):
Revision 1.3 by root, Fri May 4 13:50:02 2007 UTC vs.
Revision 1.4 by root, Fri May 4 15:16:14 2007 UTC

26#include <sys/socket.h> 26#include <sys/socket.h>
27 27
28#include <netinet/in.h> 28#include <netinet/in.h>
29#include <arpa/inet.h> 29#include <arpa/inet.h>
30 30
31#ifdef __linux
32# include <linux/icmp.h>
33#endif
34
31#define ICMP4_ECHO 8 35#define ICMP4_ECHO 8
36#define ICMP4_ECHO_REPLY 0
32#define ICMP6_ECHO 128 37#define ICMP6_ECHO 128
38#define ICMP6_ECHO_REPLY 129
33 39
34#define DRAIN_INTERVAL .000001 // how long to wait when sendto returns ENOBUFS, in seconds 40#define DRAIN_INTERVAL .000001 // how long to wait when sendto returns ENOBUFS, in seconds
35#define MIN_INTERVAL .000001 // minimum packet send interval, in seconds 41#define MIN_INTERVAL .000001 // minimum packet send interval, in seconds
36 42
37#define HDR_SIZE_IP4 20 43#define HDR_SIZE_IP4 20
185 pkt.code = 0; 191 pkt.code = 0;
186 pkt.id = (uint16_t)MAGIC; 192 pkt.id = (uint16_t)MAGIC;
187 pkt.seq = (uint16_t)~MAGIC; 193 pkt.seq = (uint16_t)~MAGIC;
188 pkt.payload = req->payload; 194 pkt.payload = req->payload;
189 195
190 tstamp next = NOW (); 196 tstamp now = NOW ();
197 tstamp next = now;
191 198
192 while (req->nranges) 199 while (req->nranges)
193 { 200 {
194 RANGE *range = req->ranges; 201 RANGE *range = req->ranges;
195 202
196 if (!memcmp (&range->lo, &range->hi, sizeof (addr_t))) 203 if (!memcmp (&range->lo, &range->hi, sizeof (addr_t)))
197 req->ranges [0] = req->ranges [--req->nranges]; 204 req->ranges [0] = req->ranges [--req->nranges];
198 else 205 else
199 { 206 {
200 tstamp now = NOW ();
201
202 // ranges [0] is always the next range to ping 207 // ranges [0] is always the next range to ping
203 tstamp wait = range->next - now; 208 tstamp wait = range->next - now;
204 209
205 // compare with the global frequency limit 210 // compare with the global frequency limit
206 { 211 {
219 ts.tv_sec = wait; 224 ts.tv_sec = wait;
220 ts.tv_nsec = (wait - ts.tv_sec) * 1000000000.; 225 ts.tv_nsec = (wait - ts.tv_sec) * 1000000000.;
221 226
222 nanosleep (&ts, 0); 227 nanosleep (&ts, 0);
223 } 228 }
229
230 now = NOW ();
224 231
225 pkt.stamp = now; 232 pkt.stamp = now;
226 pkt.cksum = 0; 233 pkt.cksum = 0;
227 234
228 if (range->family == AF_INET) 235 if (range->family == AF_INET)
346 icmp6_fd = socket (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); 353 icmp6_fd = socket (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
347#endif 354#endif
348 355
349#ifdef ICMP_FILTER 356#ifdef ICMP_FILTER
350 { 357 {
351 icmp_filter oval; 358 struct icmp_filter oval;
352 oval.data = 0xffffffff & ~(1 << ICMP4_ECHO); 359 oval.data = 0xffffffff & ~(1 << ICMP4_ECHO_REPLY);
353 setsockopt (icmpv4_fd, SOL_RAW, ICMP_FILTER, &oval, sizeof oval); 360 setsockopt (icmp4_fd, SOL_RAW, ICMP_FILTER, &oval, sizeof oval);
354 } 361 }
355#endif 362#endif
356 363
357 pthread_attr_init (&attr); 364 pthread_attr_init (&attr);
358 pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); 365 pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
387 boot (); 394 boot ();
388 395
389 newCONSTSUB (stash, "ipv4_supported", newSViv (icmp4_fd >= 0)); 396 newCONSTSUB (stash, "ipv4_supported", newSViv (icmp4_fd >= 0));
390 newCONSTSUB (stash, "ipv6_supported", newSViv (icmp6_fd >= 0)); 397 newCONSTSUB (stash, "ipv6_supported", newSViv (icmp6_fd >= 0));
391 398
392 newCONSTSUB (stash, "ipv4_pktsize", newSViv (HDR_SIZE_IP4 + sizeof (PKT))); 399 newCONSTSUB (stash, "icmp4_pktsize", newSViv (HDR_SIZE_IP4 + sizeof (PKT)));
393 newCONSTSUB (stash, "ipv6_pktsize", newSViv (HDR_SIZE_IP6 + sizeof (PKT))); 400 newCONSTSUB (stash, "icmp6_pktsize", newSViv (HDR_SIZE_IP6 + sizeof (PKT)));
394} 401}
395 402
396PROTOTYPES: DISABLE 403PROTOTYPES: DISABLE
397 404
398SV * 405SV *
540 || hdrlen < HDR_SIZE_IP4 || hdrlen + sizeof (PKT) != totlen) 547 || hdrlen < HDR_SIZE_IP4 || hdrlen + sizeof (PKT) != totlen)
541 continue; 548 continue;
542 549
543 PKT *pkt = (PKT *)(buf + hdrlen); 550 PKT *pkt = (PKT *)(buf + hdrlen);
544 551
552 if (pkt->type != ICMP4_ECHO_REPLY
545 if (pkt->id != (uint16_t)MAGIC 553 || pkt->id != (uint16_t) MAGIC
546 || pkt->seq != (uint16_t)~MAGIC 554 || pkt->seq != (uint16_t)~MAGIC
547 || pkt->type != ICMP4_ECHO
548 || !isnormal (pkt->stamp)) 555 || !isnormal (pkt->stamp))
549 continue; 556 continue;
550 557
551 AV *av = newAV (); 558 AV *av = newAV ();
552 av_push (av, newSVpvn ((char *)&sa.sin_addr, 4)); 559 av_push (av, newSVpvn ((char *)&sa.sin_addr, 4));
574 int len = recvfrom (icmp6_fd, &pkt, sizeof (pkt), MSG_DONTWAIT | MSG_TRUNC, &sa, &sl); 581 int len = recvfrom (icmp6_fd, &pkt, sizeof (pkt), MSG_DONTWAIT | MSG_TRUNC, &sa, &sl);
575 582
576 if (len != sizeof (PKT)) 583 if (len != sizeof (PKT))
577 break; 584 break;
578 585
579 if (pkt.type != ICMP6_ECHO 586 if (pkt.type != ICMP6_ECHO_REPLY
580 || pkt.id != (uint16_t)MAGIC 587 || pkt.id != (uint16_t) MAGIC
581 || pkt.seq != (uint16_t)~MAGIC 588 || pkt.seq != (uint16_t)~MAGIC
582 || !isnormal (pkt.stamp)) 589 || !isnormal (pkt.stamp))
583 continue; 590 continue;
584 591
585 AV *av = newAV (); 592 AV *av = newAV ();

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines