ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent/lib/AnyEvent/Socket.pm
(Generate patch)

Comparing AnyEvent/lib/AnyEvent/Socket.pm (file contents):
Revision 1.145 by root, Tue Mar 27 16:21:11 2012 UTC vs.
Revision 1.152 by root, Mon Apr 9 02:25:48 2012 UTC

644 644
645 resolve_sockaddr "google.com", "http", 0, undef, undef, sub { ... }; 645 resolve_sockaddr "google.com", "http", 0, undef, undef, sub { ... };
646 646
647=cut 647=cut
648 648
649our %HOSTS; 649our %HOSTS; # $HOSTS{$nodename}[$ipv6] = [@aliases...]
650our @HOSTS_CHECKING; # callbacks to call when hosts have been loaded
650our $HOSTS; 651our $HOSTS_MTIME;
651 652
652if (
653 open my $fh, "<",
654 length $ENV{PERL_ANYEVENT_HOSTS} ? $ENV{PERL_ANYEVENT_HOSTS}
655 : AnyEvent::WIN32 ? "$ENV{SystemRoot}/system32/drivers/etc/hosts"
656 : "/etc/hosts"
657) {
658 local $/;
659 binmode $fh;
660 $HOSTS = <$fh>;
661} else {
662 $HOSTS = "";
663}
664
665sub _parse_hosts() { 653sub _parse_hosts($) {
666 #%HOSTS = (); 654 %HOSTS = ();
667 655
668 for (split /\n/, $HOSTS) { 656 for (split /\n/, $_[0]) {
669 s/#.*$//; 657 s/#.*$//;
670 s/^[ \t]+//; 658 s/^[ \t]+//;
671 y/A-Z/a-z/; 659 y/A-Z/a-z/;
672 660
673 my ($addr, @aliases) = split /[ \t]+/; 661 my ($addr, @aliases) = split /[ \t]+/;
679 } elsif (my $ip = parse_ipv6 $addr) { 667 } elsif (my $ip = parse_ipv6 $addr) {
680 push @{ $HOSTS{$_}[1] }, $ip 668 push @{ $HOSTS{$_}[1] }, $ip
681 for @aliases; 669 for @aliases;
682 } 670 }
683 } 671 }
672}
684 673
685 undef $HOSTS; 674# helper function - unless dns delivered results, check and parse hosts, then clal continuation code
675sub _load_hosts_unless(&$@) {
676 my ($cont, $cv, @dns) = @_;
677
678 if (@dns) {
679 $cv->end;
680 } else {
681 my $etc_hosts = length $ENV{PERL_ANYEVENT_HOSTS} ? $ENV{PERL_ANYEVENT_HOSTS}
682 : AnyEvent::WIN32 ? "$ENV{SystemRoot}/system32/drivers/etc/hosts"
683 : "/etc/hosts";
684
685 push @HOSTS_CHECKING, sub {
686 $cont->();
687 $cv->end;
688 };
689
690 unless ($#HOSTS_CHECKING) {
691 # we are not the first, so we actually have to do the work
692 require AnyEvent::IO;
693
694 AnyEvent::IO::aio_stat ($etc_hosts, sub {
695 if ((stat _)[9] ne $HOSTS_MTIME) {
696 AE::log 8 => "(re)loading $etc_hosts.";
697 $HOSTS_MTIME = (stat _)[9];
698 # we might load a newer version of hosts,but that's a harmless race,
699 # as the next call will just load it again.
700 AnyEvent::IO::aio_load ($etc_hosts, sub {
701 _parse_hosts $_[0];
702 (shift @HOSTS_CHECKING)->() while @HOSTS_CHECKING;
703 });
704 } else {
705 (shift @HOSTS_CHECKING)->() while @HOSTS_CHECKING;
706 }
707 });
708 }
709 }
686} 710}
687 711
688sub resolve_sockaddr($$$$$$) { 712sub resolve_sockaddr($$$$$$) {
689 my ($node, $service, $proto, $family, $type, $cb) = @_; 713 my ($node, $service, $proto, $family, $type, $cb) = @_;
690 714
767 AnyEvent::DNS::a $node, sub { 791 AnyEvent::DNS::a $node, sub {
768 push @res, [$idx, "ipv4", [AF_INET , $type, $proton, pack_sockaddr $port, parse_ipv4 $_]] 792 push @res, [$idx, "ipv4", [AF_INET , $type, $proton, pack_sockaddr $port, parse_ipv4 $_]]
769 for @_; 793 for @_;
770 794
771 # dns takes precedence over hosts 795 # dns takes precedence over hosts
796 _load_hosts_unless {
772 push @res, 797 push @res,
773 map [$idx, "ipv4", [AF_INET , $type, $proton, pack_sockaddr $port, $_]], 798 map [$idx, "ipv4", [AF_INET , $type, $proton, pack_sockaddr $port, $_]],
774 @{ $hosts->[0] } 799 @{ $HOSTS{$node}[0] };
775 unless @_;
776
777 $cv->end; 800 } $cv, @_;
778 }; 801 };
779 } 802 }
780 803
781 # aaaa records 804 # aaaa records
782 if ($family != 4) { 805 if ($family != 4) {
783 $cv->begin; 806 $cv->begin;
784 AnyEvent::DNS::aaaa $node, sub { 807 AnyEvent::DNS::aaaa $node, sub {
785 push @res, [$idx, "ipv6", [AF_INET6, $type, $proton, pack_sockaddr $port, parse_ipv6 $_]] 808 push @res, [$idx, "ipv6", [AF_INET6, $type, $proton, pack_sockaddr $port, parse_ipv6 $_]]
786 for @_; 809 for @_;
787 810
811 _load_hosts_unless {
788 push @res, 812 push @res,
789 map [$idx + 0.5, "ipv6", [AF_INET6, $type, $proton, pack_sockaddr $port, $_]], 813 map [$idx + 0.5, "ipv6", [AF_INET6, $type, $proton, pack_sockaddr $port, $_]],
790 @{ $hosts->[1] } 814 @{ $HOSTS{$node}[1] }
791 unless @_;
792
793 $cv->end; 815 } $cv, @_;
794 }; 816 };
795 } 817 }
796 } 818 }
797 } 819 }
798 $cv->end; 820 $cv->end;
799 }; 821 };
800 822
801 $node = AnyEvent::Util::idn_to_ascii $node 823 $node = AnyEvent::Util::idn_to_ascii $node
802 if $node =~ /[^\x00-\x7f]/; 824 if $node =~ /[^\x00-\x7f]/;
803
804 # parse hosts
805 if (defined $HOSTS) {
806 _parse_hosts;
807 undef &_parse_hosts;
808 }
809 825
810 # try srv records, if applicable 826 # try srv records, if applicable
811 if ($node eq "localhost") { 827 if ($node eq "localhost") {
812 $resolve->(["127.0.0.1", $port], ["::1", $port]); 828 $resolve->(["127.0.0.1", $port], ["::1", $port]);
813 } elsif (defined $service && !parse_address $node) { 829 } elsif (defined $service && !parse_address $node) {
924 AE::log error => $_[2]; 940 AE::log error => $_[2];
925 $_[0]->destroy; 941 $_[0]->destroy;
926 }, 942 },
927 on_eof => sub { 943 on_eof => sub {
928 $handle->destroy; # destroy handle 944 $handle->destroy; # destroy handle
929 AE::log info => "done."; 945 AE::log info => "Done.";
930 }; 946 };
931 947
932 $handle->push_write ("GET / HTTP/1.0\015\012\015\012"); 948 $handle->push_write ("GET / HTTP/1.0\015\012\015\012");
933 949
934 $handle->push_read (line => "\015\012\015\012", sub { 950 $handle->push_read (line => "\015\012\015\012", sub {
1114 my ($fh, $host, $port) = @_; 1130 my ($fh, $host, $port) = @_;
1115 1131
1116 syswrite $fh, "The internet is full, $host:$port. Go away!\015\012"; 1132 syswrite $fh, "The internet is full, $host:$port. Go away!\015\012";
1117 }, sub { 1133 }, sub {
1118 my ($fh, $thishost, $thisport) = @_; 1134 my ($fh, $thishost, $thisport) = @_;
1119 AE::log info => "bound to $thishost, port $thisport"; 1135 AE::log info => "Bound to $thishost, port $thisport.";
1120 }; 1136 };
1121 1137
1122Example: bind a server on a unix domain socket. 1138Example: bind a server on a unix domain socket.
1123 1139
1124 tcp_server "unix/", "/tmp/mydir/mysocket", sub { 1140 tcp_server "unix/", "/tmp/mydir/mysocket", sub {
1244harmful in general. 1260harmful in general.
1245 1261
1246=head1 AUTHOR 1262=head1 AUTHOR
1247 1263
1248 Marc Lehmann <schmorp@schmorp.de> 1264 Marc Lehmann <schmorp@schmorp.de>
1249 http://home.schmorp.de/ 1265 http://anyevent.schmorp.de
1250 1266
1251=cut 1267=cut
1252 1268
12531 12691
1254 1270

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines