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.5 by root, Fri Jul 3 09:26:19 2009 UTC vs.
Revision 1.6 by root, Sat Jul 18 00:53:42 2009 UTC

182 for (;;) 182 for (;;)
183 { 183 {
184 REQ *req; 184 REQ *req;
185 int len = read (thr_send [0], &req, sizeof (req)); 185 int len = read (thr_send [0], &req, sizeof (req));
186 186
187 tstamp now = NOW ();
188 tstamp next = now;
189
187 if (!len) 190 if (!len)
188 pthread_exit (0); 191 pthread_exit (0);
189 else if (len != sizeof (req)) 192 else if (len != sizeof (req))
190 { 193 {
191 perror ("AnyEvent::FastPing: short reead or read error"); 194 perror ("AnyEvent::FastPing: short reead or read error");
197 pkt.code = 0; 200 pkt.code = 0;
198 pkt.id = (uint16_t)magic; 201 pkt.id = (uint16_t)magic;
199 pkt.seq = (uint16_t)~magic; 202 pkt.seq = (uint16_t)~magic;
200 pkt.payload = req->payload; 203 pkt.payload = req->payload;
201 204
202 tstamp now = NOW ();
203 tstamp next = now;
204
205 { 205 {
206 int r; 206 int r;
207 for (r = req->nranges; r--; ) 207 for (r = req->nranges; r--; )
208 inc_addr (&req->ranges [r].hi); 208 inc_addr (&req->ranges [r].hi);
209 } 209 }
210 210
211 while (req->nranges) 211 while (req->nranges)
212 { 212 {
213 RANGE *range = req->ranges; 213 RANGE *range = req->ranges;
214 int n, k;
214 215
215 if (!memcmp (&range->lo, &range->hi, sizeof (addr_t))) 216 if (!memcmp (&range->lo, &range->hi, sizeof (addr_t)))
216 req->ranges [0] = req->ranges [--req->nranges]; 217 req->ranges [0] = req->ranges [--req->nranges];
217 else 218 else
218 { 219 {
289 290
290 next += req->interval; 291 next += req->interval;
291 } 292 }
292 293
293 // make a downheap operation 294 // make a downheap operation
294 int k = 0;
295 int n = 0;
296 for (;;) 295 for (n = k = 0; ; )
297 { 296 {
297 int j = k * 2 + 1;
298
298 ++n; 299 ++n;
299 int j = k * 2 + 1;
300 300
301 if (j >= req->nranges) 301 if (j >= req->nranges)
302 break; 302 break;
303 else if (j < req->nranges - 1) 303 else if (j < req->nranges - 1)
304 if (req->ranges [j].next > req->ranges [j + 1].next) 304 if (req->ranges [j].next > req->ranges [j + 1].next)
305 ++j; 305 ++j;
306 306
307 if (req->ranges [j].next >= req->ranges [k].next) 307 if (req->ranges [j].next >= req->ranges [k].next)
308 break; 308 break;
309 309
310 {
310 RANGE temp = req->ranges [k]; 311 RANGE temp = req->ranges [k];
311 req->ranges [k] = req->ranges [j]; 312 req->ranges [k] = req->ranges [j];
312 req->ranges [j] = temp; 313 req->ranges [j] = temp;
314 }
313 315
314 k = j; 316 k = j;
315 } 317 }
316 } 318 }
317 319
322} 324}
323 325
324static void 326static void
325feed_reply (AV *res_av) 327feed_reply (AV *res_av)
326{ 328{
327 if (av_len (res_av) < 0)
328 return;
329
330 dSP; 329 dSP;
331 SV *res = sv_2mortal (newRV_inc ((SV *)res_av)); 330 SV *res = sv_2mortal (newRV_inc ((SV *)res_av));
332 int i; 331 int i;
332
333 if (av_len (res_av) < 0)
334 return;
333 335
334 ENTER; 336 ENTER;
335 SAVETMPS; 337 SAVETMPS;
336 338
337 for (i = av_len (cbs) + 1; i--; ) 339 for (i = av_len (cbs) + 1; i--; )
427 429
428SV * 430SV *
429_req_icmp_ping (SV *ranges, NV interval, U32 payload, SV *id) 431_req_icmp_ping (SV *ranges, NV interval, U32 payload, SV *id)
430 CODE: 432 CODE:
431{ 433{
434 AV *rav;
435 int nranges, i;
436 REQ *req;
437
432 if (!SvROK (ranges) || SvTYPE (SvRV (ranges)) != SVt_PVAV) 438 if (!SvROK (ranges) || SvTYPE (SvRV (ranges)) != SVt_PVAV)
433 croak ("address ranges must be given as arrayref with lo, hi pairs"); 439 croak ("address ranges must be given as arrayref with lo, hi pairs");
434 440
435 AV *rav = (AV *)SvRV (ranges); 441 rav = (AV *)SvRV (ranges);
436 int nranges = av_len (rav) + 1; 442 nranges = av_len (rav) + 1;
437 443
438 REQ *req = malloc (sizeof (REQ)); 444 req = malloc (sizeof (REQ));
439 int i;
440 445
441 if (interval < MIN_INTERVAL) 446 if (interval < MIN_INTERVAL)
442 interval = MIN_INTERVAL; 447 interval = MIN_INTERVAL;
443 448
444 req->id = newSVsv (id); 449 req->id = newSVsv (id);
448 req->ranges = (RANGE *)malloc (nranges * sizeof (RANGE)); 453 req->ranges = (RANGE *)malloc (nranges * sizeof (RANGE));
449 454
450 while (nranges--) 455 while (nranges--)
451 { 456 {
452 SV *sv = *av_fetch (rav, nranges, 1); 457 SV *sv = *av_fetch (rav, nranges, 1);
458 SV *lo, *hi;
459 AV *av;
460 RANGE *r;
453 461
454 if (!SvROK (sv) || SvTYPE (SvRV (sv)) != SVt_PVAV) 462 if (!SvROK (sv) || SvTYPE (SvRV (sv)) != SVt_PVAV)
455 croak ("address range must be given as arrayref with lo, hi, interval arrayrefs"); 463 croak ("address range must be given as arrayref with lo, hi, interval arrayrefs");
456 464
457 AV *av = (AV *)SvRV (sv); 465 av = (AV *)SvRV (sv);
458 RANGE *r = req->ranges + nranges; 466 r = req->ranges + nranges;
459 467
460 SV *lo = *av_fetch (av, 0, 1); 468 lo = *av_fetch (av, 0, 1);
461 SV *hi = *av_fetch (av, 1, 1); 469 hi = *av_fetch (av, 1, 1);
462 470
463 sv_utf8_downgrade (lo, 0); 471 sv_utf8_downgrade (lo, 0);
464 sv_utf8_downgrade (hi, 0); 472 sv_utf8_downgrade (hi, 0);
465 473
466 memset (&r->lo, 0, sizeof (addr_t)); 474 memset (&r->lo, 0, sizeof (addr_t));
490 else 498 else
491 croak ("addresses in range must be either 4 (IPv4) or 16 (IPv6) bytes in length"); 499 croak ("addresses in range must be either 4 (IPv4) or 16 (IPv6) bytes in length");
492 } 500 }
493 else if (SvIOK (lo) && SvIOK (hi)) 501 else if (SvIOK (lo) && SvIOK (hi))
494 { 502 {
503 uint32_t addr;
504
495 r->family = AF_INET; 505 r->family = AF_INET;
496 506
497 uint32_t addr;
498 addr = htonl (SvUV (lo)); memcpy (sizeof (addr_t) - 4 + (char *)&r->lo, &addr, 4); 507 addr = htonl (SvUV (lo)); memcpy (sizeof (addr_t) - 4 + (char *)&r->lo, &addr, 4);
499 addr = htonl (SvUV (hi)); memcpy (sizeof (addr_t) - 4 + (char *)&r->hi, &addr, 4); 508 addr = htonl (SvUV (hi)); memcpy (sizeof (addr_t) - 4 + (char *)&r->hi, &addr, 4);
500 } 509 }
501 else 510 else
502 croak ("addresses in range must be strings with either 4 (IPv4) or 16 (IPv6) octets"); 511 croak ("addresses in range must be strings with either 4 (IPv4) or 16 (IPv6) octets");
551 AV *res_av = av_len (cbs) < 0 ? 0 : (AV *)sv_2mortal ((SV *)newAV ()); 560 AV *res_av = av_len (cbs) < 0 ? 0 : (AV *)sv_2mortal ((SV *)newAV ());
552 tstamp now = NOW (); 561 tstamp now = NOW ();
553 562
554 for (;;) 563 for (;;)
555 { 564 {
565 IP4HDR *iphdr = (IP4HDR *)buf;
556 int len = recvfrom (icmp4_fd, buf, sizeof (buf), MSG_TRUNC, (struct sockaddr *)&sa, &sl); 566 int len = recvfrom (icmp4_fd, buf, sizeof (buf), MSG_TRUNC, (struct sockaddr *)&sa, &sl);
567 int hdrlen, totlen;
568 PKT *pkt;
557 569
558 if (len <= HDR_SIZE_IP4) 570 if (len <= HDR_SIZE_IP4)
559 break; 571 break;
560 572
561 IP4HDR *iphdr = (IP4HDR *)buf;
562
563 int hdrlen = (iphdr->version_ihl & 15) * 4; 573 hdrlen = (iphdr->version_ihl & 15) * 4;
564 int totlen = ntohs (iphdr->tot_len); 574 totlen = ntohs (iphdr->tot_len);
565 575
566 // packet corrupt? 576 // packet corrupt?
567 if (!res_av 577 if (!res_av
568 || totlen > len 578 || totlen > len
569 || iphdr->protocol != IPPROTO_ICMP 579 || iphdr->protocol != IPPROTO_ICMP
570 || hdrlen < HDR_SIZE_IP4 || hdrlen + sizeof (PKT) != totlen) 580 || hdrlen < HDR_SIZE_IP4 || hdrlen + sizeof (PKT) != totlen)
571 continue; 581 continue;
572 582
573 PKT *pkt = (PKT *)(buf + hdrlen); 583 pkt = (PKT *)(buf + hdrlen);
574 584
575 if (pkt->type != ICMP4_ECHO_REPLY 585 if (pkt->type != ICMP4_ECHO_REPLY
576 || pkt->id != (uint16_t) magic 586 || pkt->id != (uint16_t) magic
577 || pkt->seq != (uint16_t)~magic 587 || pkt->seq != (uint16_t)~magic
578 || !isnormal (pkt->stamp)) 588 || !isnormal (pkt->stamp))
579 continue; 589 continue;
580 590
591 {
581 AV *av = newAV (); 592 AV *av = newAV ();
582 av_push (av, newSVpvn ((char *)&sa.sin_addr, 4)); 593 av_push (av, newSVpvn ((char *)&sa.sin_addr, 4));
583 av_push (av, newSVnv (now - pkt->stamp)); 594 av_push (av, newSVnv (now - pkt->stamp));
584 av_push (av, newSVuv (pkt->payload)); 595 av_push (av, newSVuv (pkt->payload));
585 596
586 av_push (res_av, newRV_noinc ((SV *)av)); 597 av_push (res_av, newRV_noinc ((SV *)av));
598 }
587 } 599 }
588 600
589 if (res_av) 601 if (res_av)
590 feed_reply (res_av); 602 feed_reply (res_av);
591} 603}
612 || pkt.id != (uint16_t) magic 624 || pkt.id != (uint16_t) magic
613 || pkt.seq != (uint16_t)~magic 625 || pkt.seq != (uint16_t)~magic
614 || !isnormal (pkt.stamp)) 626 || !isnormal (pkt.stamp))
615 continue; 627 continue;
616 628
629 {
617 AV *av = newAV (); 630 AV *av = newAV ();
618 av_push (av, newSVpvn ((char *)&sa.sin6_addr, 16)); 631 av_push (av, newSVpvn ((char *)&sa.sin6_addr, 16));
619 av_push (av, newSVnv (now - pkt.stamp)); 632 av_push (av, newSVnv (now - pkt.stamp));
620 av_push (av, newSVuv (pkt.payload)); 633 av_push (av, newSVuv (pkt.payload));
621 634
622 av_push (res_av, newRV_noinc ((SV *)av)); 635 av_push (res_av, newRV_noinc ((SV *)av));
636 }
623 } 637 }
624 638
625 if (res_av) 639 if (res_av)
626 feed_reply (res_av); 640 feed_reply (res_av);
627} 641}

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines