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.1 by root, Sun Apr 27 15:43:51 2008 UTC vs.
Revision 1.5 by root, Fri Jul 3 09:26:19 2009 UTC

1#define _POSIX_C_SOURCE 199309 1#if defined(__linux)
2#define _GNU_SOURCE 1
3
4#define 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
4# define ENABLE_IPV6 0
5#endif
5 6
6#include "EXTERN.h" 7#include "EXTERN.h"
7#include "perl.h" 8#include "perl.h"
8#include "XSUB.h" 9#include "XSUB.h"
9 10
29#include <arpa/inet.h> 30#include <arpa/inet.h>
30 31
31#ifdef __linux 32#ifdef __linux
32# include <linux/icmp.h> 33# include <linux/icmp.h>
33#endif 34#endif
34#if IPV6 35#if ENABLE_IPV6
35# include <netinet/icmp6.h> 36# include <netinet/icmp6.h>
36#endif 37#endif
37 38
38#define ICMP4_ECHO 8 39#define ICMP4_ECHO 8
39#define ICMP4_ECHO_REPLY 0 40#define ICMP4_ECHO_REPLY 0
44#define MIN_INTERVAL .000001 // minimum packet send interval, in seconds 45#define MIN_INTERVAL .000001 // minimum packet send interval, in seconds
45 46
46#define HDR_SIZE_IP4 20 47#define HDR_SIZE_IP4 20
47#define HDR_SIZE_IP6 48 48#define HDR_SIZE_IP6 48
48 49
49//TODO: xread/xwrite for atomicity? we currently rely on the fact that the pip biffersize 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
50 51
51typedef uint8_t addr_t[16]; 52typedef uint8_t addr_t[16];
52 53
53typedef double tstamp; 54typedef double tstamp;
54 55
55tstamp 56static tstamp
56NOW () 57NOW (void)
57{ 58{
58 struct timeval tv; 59 struct timeval tv;
59 gettimeofday (&tv, 0); 60 gettimeofday (&tv, 0);
60 return tv.tv_sec + tv.tv_usec * 0.000001; 61 return tv.tv_sec + tv.tv_usec * 0.000001;
61} 62}
161static void * 162static void *
162ping_proc (void *unused) 163ping_proc (void *unused)
163{ 164{
164 PKT pkt; 165 PKT pkt;
165 struct sockaddr_in sa4; 166 struct sockaddr_in sa4;
166#if IPV6 167#if ENABLE_IPV6
167 struct sockaddr_in6 sa6; 168 struct sockaddr_in6 sa6;
168#endif 169#endif
169 170
170 memset (&pkt, 0, sizeof (pkt)); 171 memset (&pkt, 0, sizeof (pkt));
171 172
172 memset (&sa4, 0, sizeof (sa4)); 173 memset (&sa4, 0, sizeof (sa4));
173 sa4.sin_family = AF_INET; 174 sa4.sin_family = AF_INET;
174 sa4.sin_port = 0; 175 sa4.sin_port = 0;
175#if IPV6 176#if ENABLE_IPV6
176 memset (&sa6, 0, sizeof (sa6)); 177 memset (&sa6, 0, sizeof (sa6));
177 sa6.sin6_family = AF_INET6; 178 sa6.sin6_family = AF_INET6;
178 sa6.sin6_port = 0; 179 sa6.sin6_port = 0;
179#endif 180#endif
180 181
255 if (sendto (icmp4_fd, &pkt, sizeof (pkt), 0, (struct sockaddr *)&sa4, sizeof (sa4)) > 0) 256 if (sendto (icmp4_fd, &pkt, sizeof (pkt), 0, (struct sockaddr *)&sa4, sizeof (sa4)) > 0)
256 errno = 0; 257 errno = 0;
257 } 258 }
258 else 259 else
259 { 260 {
260#if IPV6 261#if ENABLE_IPV6
261 pkt.type = ICMP6_ECHO; 262 pkt.type = ICMP6_ECHO;
262 263
263 memcpy (&sa6.sin6_addr, 264 memcpy (&sa6.sin6_addr,
264 sizeof (addr_t) - sizeof (sa6.sin6_addr) + (char *)&range->lo, 265 sizeof (addr_t) - sizeof (sa6.sin6_addr) + (char *)&range->lo,
265 sizeof (sa6.sin6_addr)); 266 sizeof (sa6.sin6_addr));
358 359
359 if (pipe (thr_recv) < 0) 360 if (pipe (thr_recv) < 0)
360 croak ("AnyEvent::FastPing: unable to create receive pipe"); 361 croak ("AnyEvent::FastPing: unable to create receive pipe");
361 362
362 icmp4_fd = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP); 363 icmp4_fd = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP);
364 fcntl (icmp4_fd, F_SETFL, O_NONBLOCK);
363#ifdef ICMP_FILTER 365#ifdef ICMP_FILTER
364 { 366 {
365 struct icmp_filter oval; 367 struct icmp_filter oval;
366 oval.data = 0xffffffff & ~(1 << ICMP4_ECHO_REPLY); 368 oval.data = 0xffffffff & ~(1 << ICMP4_ECHO_REPLY);
367 setsockopt (icmp4_fd, SOL_RAW, ICMP_FILTER, &oval, sizeof oval); 369 setsockopt (icmp4_fd, SOL_RAW, ICMP_FILTER, &oval, sizeof oval);
368 } 370 }
369#endif 371#endif
370 372
371#if IPV6 373#if ENABLE_IPV6
372 icmp6_fd = socket (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); 374 icmp6_fd = socket (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
375 fcntl (icmp6_fd, F_SETFL, O_NONBLOCK);
373# ifdef ICMP6_FILTER 376# ifdef ICMP6_FILTER
374 { 377 {
375 struct icmp6_filter oval; 378 struct icmp6_filter oval;
376 ICMP6_FILTER_SETBLOCKALL (&oval); 379 ICMP6_FILTER_SETBLOCKALL (&oval);
377 ICMP6_FILTER_SETPASS (ICMP6_ECHO_REPLY, &oval); 380 ICMP6_FILTER_SETPASS (ICMP6_ECHO_REPLY, &oval);
464 memset (&r->hi, 0, sizeof (addr_t)); 467 memset (&r->hi, 0, sizeof (addr_t));
465 468
466 if (SvPOKp (lo) && SvPOKp (hi)) 469 if (SvPOKp (lo) && SvPOKp (hi))
467 { 470 {
468 if (SvCUR (lo) != SvCUR (hi)) 471 if (SvCUR (lo) != SvCUR (hi))
469 croak ("addresses in range must be of the same size (either 4 or 16 bytes)"); 472 croak ("all addresses in range must be of the same size (either 4 or 16 bytes)");
470 473
471 if (SvCUR (lo) == 4) 474 if (SvCUR (lo) == 4)
472 { 475 {
473 r->family = AF_INET; 476 r->family = AF_INET;
474 memcpy (sizeof (addr_t) - 4 + (char *)&r->lo, SvPVX (lo), 4); 477 memcpy (sizeof (addr_t) - 4 + (char *)&r->lo, SvPVX (lo), 4);
475 memcpy (sizeof (addr_t) - 4 + (char *)&r->hi, SvPVX (hi), 4); 478 memcpy (sizeof (addr_t) - 4 + (char *)&r->hi, SvPVX (hi), 4);
476 } 479 }
477 else if (SvCUR (lo) == 16) 480 else if (SvCUR (lo) == 16)
478 { 481 {
479#if IPV6 482#if ENABLE_IPV6
480 r->family = AF_INET6; 483 r->family = AF_INET6;
481 memcpy (&r->lo, SvPVX (lo), sizeof (addr_t)); 484 memcpy (&r->lo, SvPVX (lo), sizeof (addr_t));
482 memcpy (&r->hi, SvPVX (hi), sizeof (addr_t)); 485 memcpy (&r->hi, SvPVX (hi), sizeof (addr_t));
483#else 486#else
484 croak ("IPv6 not supported in this configuration"); 487 croak ("IPv6 not supported in this configuration");
485#endif 488#endif
486 } 489 }
487 else 490 else
488 croak ("addresses in range must be either 4 (IPv4) or 16 (IPV6) bytes in length"); 491 croak ("addresses in range must be either 4 (IPv4) or 16 (IPv6) bytes in length");
489 } 492 }
490 else if (SvIOK (lo) && SvIOK (hi)) 493 else if (SvIOK (lo) && SvIOK (hi))
491 { 494 {
492 r->family = AF_INET; 495 r->family = AF_INET;
493 496
548 AV *res_av = av_len (cbs) < 0 ? 0 : (AV *)sv_2mortal ((SV *)newAV ()); 551 AV *res_av = av_len (cbs) < 0 ? 0 : (AV *)sv_2mortal ((SV *)newAV ());
549 tstamp now = NOW (); 552 tstamp now = NOW ();
550 553
551 for (;;) 554 for (;;)
552 { 555 {
553 int len = recvfrom (icmp4_fd, buf, sizeof (buf), MSG_DONTWAIT | MSG_TRUNC, &sa, &sl); 556 int len = recvfrom (icmp4_fd, buf, sizeof (buf), MSG_TRUNC, (struct sockaddr *)&sa, &sl);
554 557
555 if (len <= HDR_SIZE_IP4) 558 if (len <= HDR_SIZE_IP4)
556 break; 559 break;
557 560
558 IP4HDR *iphdr = (IP4HDR *)buf; 561 IP4HDR *iphdr = (IP4HDR *)buf;
597 PKT pkt; 600 PKT pkt;
598 tstamp now = NOW (); 601 tstamp now = NOW ();
599 602
600 for (;;) 603 for (;;)
601 { 604 {
602 int len = recvfrom (icmp6_fd, &pkt, sizeof (pkt), MSG_DONTWAIT | MSG_TRUNC, &sa, &sl); 605 int len = recvfrom (icmp6_fd, &pkt, sizeof (pkt), MSG_TRUNC, (struct sockaddr *)&sa, &sl);
603 606
604 if (len != sizeof (PKT)) 607 if (len != sizeof (PKT))
605 break; 608 break;
606 609
607 if (!res_av 610 if (!res_av

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines