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.36 by root, Wed May 28 21:29:03 2008 UTC vs.
Revision 1.50 by root, Fri Jun 6 15:35:30 2008 UTC

2 2
3AnyEvent::Socket - useful IPv4 and IPv6 stuff. 3AnyEvent::Socket - useful IPv4 and IPv6 stuff.
4 4
5=head1 SYNOPSIS 5=head1 SYNOPSIS
6 6
7 use AnyEvent::Socket; 7 use AnyEvent::Socket;
8 8
9 tcp_connect "gameserver.deliantra.net", 13327, sub { 9 tcp_connect "gameserver.deliantra.net", 13327, sub {
10 my ($fh) = @_ 10 my ($fh) = @_
11 or die "gameserver.deliantra.net connect failed: $!"; 11 or die "gameserver.deliantra.net connect failed: $!";
12 12
13 # enjoy your filehandle 13 # enjoy your filehandle
14 }; 14 };
15 15
16 # a simple tcp server 16 # a simple tcp server
17 tcp_server undef, 8888, sub { 17 tcp_server undef, 8888, sub {
18 my ($fh, $host, $port) = @_; 18 my ($fh, $host, $port) = @_;
19 19
20 syswrite $fh, "The internet is full, $host:$port. Go away!\015\012"; 20 syswrite $fh, "The internet is full, $host:$port. Go away!\015\012";
21 }; 21 };
22 22
23=head1 DESCRIPTION 23=head1 DESCRIPTION
24 24
25This module implements various utility functions for handling internet 25This module implements various utility functions for handling internet
26protocol addresses and sockets, in an as transparent and simple way as 26protocol addresses and sockets, in an as transparent and simple way as
56 inet_aton 56 inet_aton
57 tcp_server 57 tcp_server
58 tcp_connect 58 tcp_connect
59); 59);
60 60
61our $VERSION = '1.0'; 61our $VERSION = 4.151;
62 62
63=item $ipn = parse_ipv4 $dotted_quad 63=item $ipn = parse_ipv4 $dotted_quad
64 64
65Tries to parse the given dotted quad IPv4 address and return it in 65Tries to parse the given dotted quad IPv4 address and return it in
66octet form (or undef when it isn't in a parsable format). Supports all 66octet form (or undef when it isn't in a parsable format). Supports all
196sub format_address($) { 196sub format_address($) {
197 my $af = address_family $_[0]; 197 my $af = address_family $_[0];
198 if ($af == AF_INET) { 198 if ($af == AF_INET) {
199 return join ".", unpack "C4", $_[0] 199 return join ".", unpack "C4", $_[0]
200 } elsif ($af == AF_INET6) { 200 } elsif ($af == AF_INET6) {
201 if (v0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 eq $_[0]) {
202 return "::";
203 } elsif (v0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1 eq $_[0]) {
204 return "::1";
201 if (v0.0.0.0.0.0.0.0.0.0.0.0 eq substr $_[0], 0, 12) { 205 } elsif (v0.0.0.0.0.0.0.0.0.0.0.0 eq substr $_[0], 0, 12) {
202 # v4compatible 206 # v4compatible
203 return "::" . format_address substr $_[0], 12; 207 return "::" . format_address substr $_[0], 12;
204 } elsif (v0.0.0.0.0.0.0.0.0.0.255.255 eq substr $_[0], 0, 12) { 208 } elsif (v0.0.0.0.0.0.0.0.0.0.255.255 eq substr $_[0], 0, 12) {
205 # v4mapped 209 # v4mapped
206 return "::ffff:" . format_address substr $_[0], 12; 210 return "::ffff:" . format_address substr $_[0], 12;
208 # v4translated 212 # v4translated
209 return "::ffff:0:" . format_address substr $_[0], 12; 213 return "::ffff:0:" . format_address substr $_[0], 12;
210 } else { 214 } else {
211 my $ip = sprintf "%x:%x:%x:%x:%x:%x:%x:%x", unpack "n8", $_[0]; 215 my $ip = sprintf "%x:%x:%x:%x:%x:%x:%x:%x", unpack "n8", $_[0];
212 216
217 # this is rather sucky, I admit
213 $ip =~ s/^0:(?:0:)*(0$)?/::/ 218 $ip =~ s/^0:(?:0:)*(0$)?/::/
214 or $ip =~ s/(:0)+$/::/ 219 or $ip =~ s/(:0){7}$/::/ or $ip =~ s/(:0){7}/:/
215 or $ip =~ s/(:0)+/:/; 220 or $ip =~ s/(:0){6}$/::/ or $ip =~ s/(:0){6}/:/
221 or $ip =~ s/(:0){5}$/::/ or $ip =~ s/(:0){5}/:/
222 or $ip =~ s/(:0){4}$/::/ or $ip =~ s/(:0){4}/:/
223 or $ip =~ s/(:0){3}$/::/ or $ip =~ s/(:0){3}/:/
224 or $ip =~ s/(:0){2}$/::/ or $ip =~ s/(:0){2}/:/
225 or $ip =~ s/(:0){1}$/::/ or $ip =~ s/(:0){1}/:/;
216 return $ip 226 return $ip
217 } 227 }
218 } elsif ($af == AF_UNIX) { 228 } elsif ($af == AF_UNIX) {
219 return "unix/" 229 return "unix/"
220 } else { 230 } else {
262 272
263# check for broken platforms with extra field in sockaddr structure 273# check for broken platforms with extra field in sockaddr structure
264# kind of a rfc vs. bsd issue, as usual (ok, normally it's a 274# kind of a rfc vs. bsd issue, as usual (ok, normally it's a
265# unix vs. bsd issue, a iso C vs. bsd issue or simply a 275# unix vs. bsd issue, a iso C vs. bsd issue or simply a
266# correctness vs. bsd issue. 276# correctness vs. bsd issue.
267my $pack_family = 0x55 == Socket::sockaddr_family "\x55\x55" 277my $pack_family = (0x55 == Socket::sockaddr_family "\x55\x55")
268 ? "xC" : "S"; 278 ? "xC" : "S";
269 279
270=item $sa = AnyEvent::Socket::pack_sockaddr $service, $host 280=item $sa = AnyEvent::Socket::pack_sockaddr $service, $host
271 281
272Pack the given port/host combination into a binary sockaddr 282Pack the given port/host combination into a binary sockaddr
424 $cv->begin; 434 $cv->begin;
425 for my $idx (0 .. $#target) { 435 for my $idx (0 .. $#target) {
426 my ($node, $port) = @{ $target[$idx] }; 436 my ($node, $port) = @{ $target[$idx] };
427 437
428 if (my $noden = parse_address $node) { 438 if (my $noden = parse_address $node) {
439 my $af = address_family $noden;
440
429 if (4 == length $noden && $family != 6) { 441 if ($af == AF_INET && $family != 6) {
430 push @res, [$idx, "ipv4", [AF_INET, $type, $proton, 442 push @res, [$idx, "ipv4", [AF_INET, $type, $proton,
431 pack_sockaddr $port, $noden]] 443 pack_sockaddr $port, $noden]]
432 } 444 }
433 445
434 if (16 == length $noden && $family != 4) { 446 if ($af == AF_INET6 && $family != 4) {
435 push @res, [$idx, "ipv6", [AF_INET6, $type, $proton, 447 push @res, [$idx, "ipv6", [AF_INET6, $type, $proton,
436 pack_sockaddr $port, $noden]] 448 pack_sockaddr $port, $noden]]
437 } 449 }
438 } else { 450 } else {
439 # ipv4 451 # ipv4
440 if ($family != 6) { 452 if ($family != 6) {
441 $cv->begin; 453 $cv->begin;
442 a $node, sub { 454 AnyEvent::DNS::a $node, sub {
443 push @res, [$idx, "ipv4", [AF_INET, $type, $proton, 455 push @res, [$idx, "ipv4", [AF_INET, $type, $proton,
444 pack_sockaddr $port, parse_ipv4 $_]] 456 pack_sockaddr $port, parse_ipv4 $_]]
445 for @_; 457 for @_;
446 $cv->end; 458 $cv->end;
447 }; 459 };
448 } 460 }
449 461
450 # ipv6 462 # ipv6
451 if ($family != 4) { 463 if ($family != 4) {
452 $cv->begin; 464 $cv->begin;
453 aaaa $node, sub { 465 AnyEvent::DNS::aaaa $node, sub {
454 push @res, [$idx, "ipv6", [AF_INET6, $type, $proton, 466 push @res, [$idx, "ipv6", [AF_INET6, $type, $proton,
455 pack_sockaddr $port, parse_ipv6 $_]] 467 pack_sockaddr $port, parse_ipv6 $_]]
456 for @_; 468 for @_;
457 $cv->end; 469 $cv->end;
458 }; 470 };
465 # try srv records, if applicable 477 # try srv records, if applicable
466 if ($node eq "localhost") { 478 if ($node eq "localhost") {
467 @target = (["127.0.0.1", $port], ["::1", $port]); 479 @target = (["127.0.0.1", $port], ["::1", $port]);
468 &$resolve; 480 &$resolve;
469 } elsif (defined $service && !parse_address $node) { 481 } elsif (defined $service && !parse_address $node) {
470 srv $service, $proto, $node, sub { 482 AnyEvent::DNS::srv $service, $proto, $node, sub {
471 my (@srv) = @_; 483 my (@srv) = @_;
472 484
473 # no srv records, continue traditionally 485 # no srv records, continue traditionally
474 @srv 486 @srv
475 or return &$resolve; 487 or return &$resolve;
476 488
477 # only srv record has "." => abort 489 # the only srv record has "." ("" here) => abort
478 $srv[0][2] ne "." || $#srv 490 $srv[0][2] ne "" || $#srv
479 or return $cb->(); 491 or return $cb->();
480 492
481 # use srv records then 493 # use srv records then
482 @target = map ["$_->[3].", $_->[2]], 494 @target = map ["$_->[3].", $_->[2]],
483 grep $_->[3] ne ".", 495 grep $_->[3] ne ".",
548lessen the impact of this windows bug, a default timeout of 30 seconds 560lessen the impact of this windows bug, a default timeout of 30 seconds
549will be imposed on windows. Cygwin is not affected. 561will be imposed on windows. Cygwin is not affected.
550 562
551Simple Example: connect to localhost on port 22. 563Simple Example: connect to localhost on port 22.
552 564
553 tcp_connect localhost => 22, sub { 565 tcp_connect localhost => 22, sub {
554 my $fh = shift 566 my $fh = shift
555 or die "unable to connect: $!"; 567 or die "unable to connect: $!";
556 # do something 568 # do something
557 }; 569 };
558 570
559Complex Example: connect to www.google.com on port 80 and make a simple 571Complex Example: connect to www.google.com on port 80 and make a simple
560GET request without much error handling. Also limit the connection timeout 572GET request without much error handling. Also limit the connection timeout
561to 15 seconds. 573to 15 seconds.
562 574
691Create and bind a stream socket to the given host, and port, set the 703Create and bind a stream socket to the given host, and port, set the
692SO_REUSEADDR flag (if applicable) and call C<listen>. Unlike the name 704SO_REUSEADDR flag (if applicable) and call C<listen>. Unlike the name
693implies, this function can also bind on UNIX domain sockets. 705implies, this function can also bind on UNIX domain sockets.
694 706
695For internet sockets, C<$host> must be an IPv4 or IPv6 address (or 707For internet sockets, C<$host> must be an IPv4 or IPv6 address (or
696C<undef>, in which case it binds either to C<0> or to C<::>, depending on 708C<undef>, in which case it binds either to C<0> or to C<::>, depending
697whether IPv4 or IPv6 is the preferred protocol). 709on whether IPv4 or IPv6 is the preferred protocol, and maybe to both in
710future versions, as applicable).
698 711
699To bind to the IPv4 wildcard address, use C<0>, to bind to the IPv6 712To bind to the IPv4 wildcard address, use C<0>, to bind to the IPv6
700wildcard address, use C<::>. 713wildcard address, use C<::>.
701 714
702The port is specified by C<$service>, which must be either a service name or 715The port is specified by C<$service>, which must be either a service name or
726address and port number of the local socket endpoint as second and third 739address and port number of the local socket endpoint as second and third
727arguments. 740arguments.
728 741
729It should return the length of the listen queue (or C<0> for the default). 742It should return the length of the listen queue (or C<0> for the default).
730 743
744Note to IPv6 users: RFC-compliant behaviour for IPv6 sockets listening on
745C<::> is to bind to both IPv6 and IPv4 addresses by default on dual-stack
746hosts. Unfortunately, only GNU/Linux seems to implement this properly, so
747if you want both IPv4 and IPv6 listening sockets you should create the
748IPv6 socket first and then attempt to bind on the IPv4 socket, but ignore
749any C<EADDRINUSE> errors.
750
731Example: bind on some TCP port on the local machine and tell each client 751Example: bind on some TCP port on the local machine and tell each client
732to go away. 752to go away.
733 753
734 tcp_server undef, undef, sub { 754 tcp_server undef, undef, sub {
735 my ($fh, $host, $port) = @_; 755 my ($fh, $host, $port) = @_;
764 or Carp::croak "tcp_server/socket: $!"; 784 or Carp::croak "tcp_server/socket: $!";
765 785
766 if ($af == AF_INET || $af == AF_INET6) { 786 if ($af == AF_INET || $af == AF_INET6) {
767 setsockopt $state{fh}, SOL_SOCKET, SO_REUSEADDR, 1 787 setsockopt $state{fh}, SOL_SOCKET, SO_REUSEADDR, 1
768 or Carp::croak "tcp_server/so_reuseaddr: $!" 788 or Carp::croak "tcp_server/so_reuseaddr: $!"
769 unless !AnyEvent::WIN32; # work around windows bug 789 unless AnyEvent::WIN32; # work around windows bug
770 790
771 unless ($service =~ /^\d*$/) { 791 unless ($service =~ /^\d*$/) {
772 $service = (getservbyname $service, "tcp")[2] 792 $service = (getservbyname $service, "tcp")[2]
773 or Carp::croak "$service: service unknown" 793 or Carp::croak "$service: service unknown"
774 } 794 }
795 815
796 $state{aw} = AnyEvent->io (fh => $state{fh}, poll => 'r', cb => sub { 816 $state{aw} = AnyEvent->io (fh => $state{fh}, poll => 'r', cb => sub {
797 # this closure keeps $state alive 817 # this closure keeps $state alive
798 while (my $peer = accept my $fh, $state{fh}) { 818 while (my $peer = accept my $fh, $state{fh}) {
799 fh_nonblocking $fh, 1; # POSIX requires inheritance, the outside world does not 819 fh_nonblocking $fh, 1; # POSIX requires inheritance, the outside world does not
820
800 my ($service, $host) = unpack_sockaddr $peer; 821 my ($service, $host) = unpack_sockaddr $peer;
801 $accept->($fh, format_address $host, $service); 822 $accept->($fh, format_address $host, $service);
802 } 823 }
803 }); 824 });
804 825
809 830
8101; 8311;
811 832
812=back 833=back
813 834
835=head1 SECURITY CONSIDERATIONS
836
837This module is quite powerful, with with power comes the ability to abuse
838as well: If you accept "hostnames" and ports from untrusted sources,
839then note that this can be abused to delete files (host=C<unix/>). This
840is not really a problem with this module, however, as blindly accepting
841any address and protocol and trying to bind a server or connect to it is
842harmful in general.
843
814=head1 AUTHOR 844=head1 AUTHOR
815 845
816 Marc Lehmann <schmorp@schmorp.de> 846 Marc Lehmann <schmorp@schmorp.de>
817 http://home.schmorp.de/ 847 http://home.schmorp.de/
818 848

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines