… | |
… | |
33 | |
33 | |
34 | =cut |
34 | =cut |
35 | |
35 | |
36 | package AnyEvent::Socket; |
36 | package AnyEvent::Socket; |
37 | |
37 | |
38 | no warnings; |
|
|
39 | use strict; |
|
|
40 | |
|
|
41 | use Carp (); |
38 | use Carp (); |
42 | use Errno (); |
39 | use Errno (); |
43 | use Socket qw(AF_INET AF_UNIX SOCK_STREAM SOCK_DGRAM SOL_SOCKET SO_REUSEADDR); |
40 | use Socket qw(AF_INET AF_UNIX SOCK_STREAM SOCK_DGRAM SOL_SOCKET SO_REUSEADDR); |
44 | |
41 | |
45 | use AnyEvent (); |
42 | use AnyEvent (); BEGIN { AnyEvent::common_sense } |
46 | use AnyEvent::Util qw(guard fh_nonblocking AF_INET6); |
43 | use AnyEvent::Util qw(guard fh_nonblocking AF_INET6); |
47 | use AnyEvent::DNS (); |
44 | use AnyEvent::DNS (); |
48 | |
45 | |
49 | use base 'Exporter'; |
46 | use base 'Exporter'; |
50 | |
47 | |
51 | our @EXPORT = qw( |
48 | our @EXPORT = qw( |
|
|
49 | getprotobyname |
52 | parse_hostport |
50 | parse_hostport |
53 | parse_ipv4 parse_ipv6 |
51 | parse_ipv4 parse_ipv6 |
54 | parse_ip parse_address |
52 | parse_ip parse_address |
55 | format_ipv4 format_ipv6 |
53 | format_ipv4 format_ipv6 |
56 | format_ip format_address |
54 | format_ip format_address |
… | |
… | |
58 | inet_aton |
56 | inet_aton |
59 | tcp_server |
57 | tcp_server |
60 | tcp_connect |
58 | tcp_connect |
61 | ); |
59 | ); |
62 | |
60 | |
63 | our $VERSION = 4.81; |
61 | our $VERSION = 4.83; |
64 | |
62 | |
65 | =item $ipn = parse_ipv4 $dotted_quad |
63 | =item $ipn = parse_ipv4 $dotted_quad |
66 | |
64 | |
67 | Tries to parse the given dotted quad IPv4 address and return it in |
65 | Tries to parse the given dotted quad IPv4 address and return it in |
68 | octet form (or undef when it isn't in a parsable format). Supports all |
66 | octet form (or undef when it isn't in a parsable format). Supports all |
… | |
… | |
178 | } |
176 | } |
179 | } |
177 | } |
180 | } |
178 | } |
181 | |
179 | |
182 | *aton = \&parse_address; |
180 | *aton = \&parse_address; |
|
|
181 | |
|
|
182 | =item ($name, $aliases, $proto) = getprotobyname $name |
|
|
183 | |
|
|
184 | Works like the builtin function of the same name, except it tries hard to |
|
|
185 | work even on broken platforms (well, that's windows), where getprotobyname |
|
|
186 | is traditionally very unreliable. |
|
|
187 | |
|
|
188 | =cut |
|
|
189 | |
|
|
190 | # microsoft can't even get getprotobyname working (the etc/protocols file |
|
|
191 | # gets lost fairly often on windows), so we have to hardcode some common |
|
|
192 | # protocol numbers ourselves. |
|
|
193 | our %PROTO_BYNAME; |
|
|
194 | |
|
|
195 | $PROTO_BYNAME{tcp} = Socket::IPPROTO_TCP () if defined &Socket::IPPROTO_TCP; |
|
|
196 | $PROTO_BYNAME{udp} = Socket::IPPROTO_UDP () if defined &Socket::IPPROTO_UDP; |
|
|
197 | $PROTO_BYNAME{icmp} = Socket::IPPROTO_ICMP() if defined &Socket::IPPROTO_ICMP; |
|
|
198 | |
|
|
199 | sub getprotobyname($) { |
|
|
200 | my $name = lc shift; |
|
|
201 | |
|
|
202 | defined (my $proton = $PROTO_BYNAME{$name} || (getprotobyname $name)[2]) |
|
|
203 | or return; |
|
|
204 | |
|
|
205 | ($name, uc $name, $proton) |
|
|
206 | } |
183 | |
207 | |
184 | =item ($host, $service) = parse_hostport $string[, $default_service] |
208 | =item ($host, $service) = parse_hostport $string[, $default_service] |
185 | |
209 | |
186 | Splitting a string of the form C<hostname:port> is a common |
210 | Splitting a string of the form C<hostname:port> is a common |
187 | problem. Unfortunately, just splitting on the colon makes it hard to |
211 | problem. Unfortunately, just splitting on the colon makes it hard to |
… | |
… | |
392 | } |
416 | } |
393 | }); |
417 | }); |
394 | } |
418 | } |
395 | } |
419 | } |
396 | |
420 | |
|
|
421 | BEGIN { |
|
|
422 | *sockaddr_family = $Socket::VERSION >= 1.75 |
|
|
423 | ? \&Socket::sockaddr_family |
|
|
424 | : # for 5.6.x, we need to do something much more horrible |
|
|
425 | (Socket::pack_sockaddr_in 0x5555, "\x55\x55\x55\x55" |
|
|
426 | | eval { Socket::pack_sockaddr_un "U" }) =~ /^\x00/ |
|
|
427 | ? sub { unpack "xC", $_[0] } |
|
|
428 | : sub { unpack "S" , $_[0] }; |
|
|
429 | } |
|
|
430 | |
397 | # check for broken platforms with extra field in sockaddr structure |
431 | # check for broken platforms with extra field in sockaddr structure |
398 | # kind of a rfc vs. bsd issue, as usual (ok, normally it's a |
432 | # kind of a rfc vs. bsd issue, as usual (ok, normally it's a |
399 | # unix vs. bsd issue, a iso C vs. bsd issue or simply a |
433 | # unix vs. bsd issue, a iso C vs. bsd issue or simply a |
400 | # correctness vs. bsd issue. |
434 | # correctness vs. bsd issue.) |
401 | my $pack_family = (0x55 == Socket::sockaddr_family "\x55\x55") |
435 | my $pack_family = 0x55 == sockaddr_family ("\x55\x55") |
402 | ? "xC" : "S"; |
436 | ? "xC" : "S"; |
403 | |
437 | |
404 | =item $sa = AnyEvent::Socket::pack_sockaddr $service, $host |
438 | =item $sa = AnyEvent::Socket::pack_sockaddr $service, $host |
405 | |
439 | |
406 | Pack the given port/host combination into a binary sockaddr |
440 | Pack the given port/host combination into a binary sockaddr |
… | |
… | |
442 | module (C<format_address> converts it to C<unix/>). |
476 | module (C<format_address> converts it to C<unix/>). |
443 | |
477 | |
444 | =cut |
478 | =cut |
445 | |
479 | |
446 | sub unpack_sockaddr($) { |
480 | sub unpack_sockaddr($) { |
447 | my $af = Socket::sockaddr_family $_[0]; |
481 | my $af = sockaddr_family $_[0]; |
448 | |
482 | |
449 | if ($af == AF_INET) { |
483 | if ($af == AF_INET) { |
450 | Socket::unpack_sockaddr_in $_[0] |
484 | Socket::unpack_sockaddr_in $_[0] |
451 | } elsif ($af == AF_INET6) { |
485 | } elsif ($af == AF_INET6) { |
452 | unpack "x2 n x4 a16", $_[0] |
486 | unpack "x2 n x4 a16", $_[0] |
… | |
… | |
499 | |
533 | |
500 | resolve_sockaddr "google.com", "http", 0, undef, undef, sub { ... }; |
534 | resolve_sockaddr "google.com", "http", 0, undef, undef, sub { ... }; |
501 | |
535 | |
502 | =cut |
536 | =cut |
503 | |
537 | |
504 | # microsoft can't even get getprotobyname working (the etc/protocols file |
|
|
505 | # gets lost fairly often on windows), so we have to hardcode some common |
|
|
506 | # protocol numbers ourselves. |
|
|
507 | our %PROTO_BYNAME; |
|
|
508 | |
|
|
509 | $PROTO_BYNAME{tcp} = &Socket::IPPROTO_TCP if defined &Socket::IPPROTO_TCP; |
|
|
510 | $PROTO_BYNAME{udp} = &Socket::IPPROTO_UDP if defined &Socket::IPPROTO_UDP; |
|
|
511 | $PROTO_BYNAME{icmp} = &Socket::IPPROTO_ICMP if defined &Socket::IPPROTO_ICMP; |
|
|
512 | |
|
|
513 | sub resolve_sockaddr($$$$$$) { |
538 | sub resolve_sockaddr($$$$$$) { |
514 | my ($node, $service, $proto, $family, $type, $cb) = @_; |
539 | my ($node, $service, $proto, $family, $type, $cb) = @_; |
515 | |
540 | |
516 | if ($node eq "unix/") { |
541 | if ($node eq "unix/") { |
517 | return $cb->() if $family || $service !~ /^\//; # no can do |
542 | return $cb->() if $family || $service !~ /^\//; # no can do |
… | |
… | |
533 | $family ||= 6 unless $AnyEvent::PROTOCOL{ipv4}; |
558 | $family ||= 6 unless $AnyEvent::PROTOCOL{ipv4}; |
534 | |
559 | |
535 | $proto ||= "tcp"; |
560 | $proto ||= "tcp"; |
536 | $type ||= $proto eq "udp" ? SOCK_DGRAM : SOCK_STREAM; |
561 | $type ||= $proto eq "udp" ? SOCK_DGRAM : SOCK_STREAM; |
537 | |
562 | |
538 | my $proton = $PROTO_BYNAME{lc $proto} || (getprotobyname $proto)[2] |
563 | my $proton = getprotobyname $proto |
539 | or Carp::croak "$proto: protocol unknown"; |
564 | or Carp::croak "$proto: protocol unknown"; |
540 | |
565 | |
541 | my $port; |
566 | my $port; |
542 | |
567 | |
543 | if ($service =~ /^(\S+)=(\d+)$/) { |
568 | if ($service =~ /^(\S+)=(\d+)$/) { |
… | |
… | |
712 | or die "unable to connect: $!"; |
737 | or die "unable to connect: $!"; |
713 | |
738 | |
714 | my $handle; # avoid direct assignment so on_eof has it in scope. |
739 | my $handle; # avoid direct assignment so on_eof has it in scope. |
715 | $handle = new AnyEvent::Handle |
740 | $handle = new AnyEvent::Handle |
716 | fh => $fh, |
741 | fh => $fh, |
|
|
742 | on_error => sub { |
|
|
743 | warn "error $_[2]\n"; |
|
|
744 | $_[0]->destroy; |
|
|
745 | }, |
717 | on_eof => sub { |
746 | on_eof => sub { |
718 | undef $handle; # keep it alive till eof |
747 | $handle->destroy; # destroy handle |
719 | warn "done.\n"; |
748 | warn "done.\n"; |
720 | }; |
749 | }; |
721 | |
750 | |
722 | $handle->push_write ("GET / HTTP/1.0\015\012\015\012"); |
751 | $handle->push_write ("GET / HTTP/1.0\015\012\015\012"); |
723 | |
752 | |
… | |
… | |
762 | |
791 | |
763 | $state{next} = sub { |
792 | $state{next} = sub { |
764 | return unless exists $state{fh}; |
793 | return unless exists $state{fh}; |
765 | |
794 | |
766 | my $target = shift @target |
795 | my $target = shift @target |
767 | or do { |
|
|
768 | %state = (); |
|
|
769 | return $connect->(); |
796 | or return (%state = (), $connect->()); |
770 | }; |
|
|
771 | |
797 | |
772 | my ($domain, $type, $proto, $sockaddr) = @$target; |
798 | my ($domain, $type, $proto, $sockaddr) = @$target; |
773 | |
799 | |
774 | # socket creation |
800 | # socket creation |
775 | socket $state{fh}, $domain, $type, $proto |
801 | socket $state{fh}, $domain, $type, $proto |
… | |
… | |
780 | my $timeout = $prepare && $prepare->($state{fh}); |
806 | my $timeout = $prepare && $prepare->($state{fh}); |
781 | |
807 | |
782 | $timeout ||= 30 if AnyEvent::WIN32; |
808 | $timeout ||= 30 if AnyEvent::WIN32; |
783 | |
809 | |
784 | $state{to} = AnyEvent->timer (after => $timeout, cb => sub { |
810 | $state{to} = AnyEvent->timer (after => $timeout, cb => sub { |
785 | $! = &Errno::ETIMEDOUT; |
811 | $! = Errno::ETIMEDOUT; |
786 | $state{next}(); |
812 | $state{next}(); |
787 | }) if $timeout; |
813 | }) if $timeout; |
788 | |
814 | |
789 | # called when the connect was successful, which, |
815 | # called when the connect was successful, which, |
790 | # in theory, could be the case immediately (but never is in practise) |
816 | # in theory, could be the case immediately (but never is in practise) |
791 | $state{connected} = sub { |
817 | $state{connected} = sub { |
792 | delete $state{ww}; |
|
|
793 | delete $state{to}; |
|
|
794 | |
|
|
795 | # we are connected, or maybe there was an error |
818 | # we are connected, or maybe there was an error |
796 | if (my $sin = getpeername $state{fh}) { |
819 | if (my $sin = getpeername $state{fh}) { |
797 | my ($port, $host) = unpack_sockaddr $sin; |
820 | my ($port, $host) = unpack_sockaddr $sin; |
|
|
821 | |
|
|
822 | delete $state{ww}; delete $state{to}; |
798 | |
823 | |
799 | my $guard = guard { %state = () }; |
824 | my $guard = guard { %state = () }; |
800 | |
825 | |
801 | $connect->(delete $state{fh}, format_address $host, $port, sub { |
826 | $connect->(delete $state{fh}, format_address $host, $port, sub { |
802 | $guard->cancel; |
827 | $guard->cancel; |
803 | $state{next}(); |
828 | $state{next}(); |
804 | }); |
829 | }); |
805 | } else { |
830 | } else { |
806 | # dummy read to fetch real error code |
831 | # dummy read to fetch real error code |
807 | sysread $state{fh}, my $buf, 1 if $! == &Errno::ENOTCONN; |
832 | sysread $state{fh}, my $buf, 1 if $! == Errno::ENOTCONN; |
|
|
833 | |
|
|
834 | return if $! == Errno::EAGAIN; # skip spurious wake-ups |
|
|
835 | |
|
|
836 | delete $state{ww}; delete $state{to}; |
|
|
837 | |
808 | $state{next}(); |
838 | $state{next}(); |
809 | } |
839 | } |
810 | }; |
840 | }; |
811 | |
841 | |
812 | # now connect |
842 | # now connect |
813 | if (connect $state{fh}, $sockaddr) { |
843 | if (connect $state{fh}, $sockaddr) { |
814 | $state{connected}->(); |
844 | $state{connected}->(); |
815 | } elsif ($! == &Errno::EINPROGRESS # POSIX |
845 | } elsif ($! == Errno::EINPROGRESS # POSIX |
816 | || $! == &Errno::EWOULDBLOCK |
846 | || $! == Errno::EWOULDBLOCK |
817 | # WSAEINPROGRESS intentionally not checked - it means something else entirely |
847 | # WSAEINPROGRESS intentionally not checked - it means something else entirely |
818 | || $! == AnyEvent::Util::WSAEINVAL # not convinced, but doesn't hurt |
848 | || $! == AnyEvent::Util::WSAEINVAL # not convinced, but doesn't hurt |
819 | || $! == AnyEvent::Util::WSAEWOULDBLOCK) { |
849 | || $! == AnyEvent::Util::WSAEWOULDBLOCK) { |
820 | $state{ww} = AnyEvent->io (fh => $state{fh}, poll => 'w', cb => $state{connected}); |
850 | $state{ww} = AnyEvent->io (fh => $state{fh}, poll => 'w', cb => $state{connected}); |
821 | } else { |
851 | } else { |
822 | $state{next}(); |
852 | $state{next}(); |
823 | } |
853 | } |
824 | }; |
854 | }; |
825 | |
855 | |
826 | $! = &Errno::ENXIO; |
856 | $! = Errno::ENXIO; |
827 | $state{next}(); |
857 | $state{next}(); |
828 | }; |
858 | }; |
829 | |
859 | |
830 | defined wantarray && guard { %state = () } |
860 | defined wantarray && guard { %state = () } |
831 | } |
861 | } |