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.80 by root, Fri Jun 26 06:33:17 2009 UTC vs.
Revision 1.94 by root, Fri Jul 17 14:57:03 2009 UTC

47use AnyEvent::DNS (); 47use AnyEvent::DNS ();
48 48
49use base 'Exporter'; 49use base 'Exporter';
50 50
51our @EXPORT = qw( 51our @EXPORT = qw(
52 getprotobyname
52 parse_hostport 53 parse_hostport
53 parse_ipv4 parse_ipv6 54 parse_ipv4 parse_ipv6
54 parse_ip parse_address 55 parse_ip parse_address
56 format_ipv4 format_ipv6
55 format_ip format_address 57 format_ip format_address
56 address_family 58 address_family
57 inet_aton 59 inet_aton
58 tcp_server 60 tcp_server
59 tcp_connect 61 tcp_connect
60); 62);
61 63
62our $VERSION = 4.42; 64our $VERSION = 4.83;
63 65
64=item $ipn = parse_ipv4 $dotted_quad 66=item $ipn = parse_ipv4 $dotted_quad
65 67
66Tries to parse the given dotted quad IPv4 address and return it in 68Tries to parse the given dotted quad IPv4 address and return it in
67octet form (or undef when it isn't in a parsable format). Supports all 69octet form (or undef when it isn't in a parsable format). Supports all
144 ? pack "S", AF_UNIX 146 ? pack "S", AF_UNIX
145 : undef 147 : undef
146 148
147} 149}
148 150
149=item $ipn = parse_address $text 151=item $ipn = parse_address $ip
150 152
151Combines C<parse_ipv4> and C<parse_ipv6> in one function. The address 153Combines C<parse_ipv4> and C<parse_ipv6> in one function. The address
152here refers to the host address (not socket address) in network form 154here refers to the host address (not socket address) in network form
153(binary). 155(binary).
154 156
155If the C<$text> is C<unix/>, then this function returns a special token 157If the C<$text> is C<unix/>, then this function returns a special token
156recognised by the other functions in this module to mean "UNIX domain 158recognised by the other functions in this module to mean "UNIX domain
157socket". 159socket".
158 160
161If the C<$text> to parse is a mapped IPv4 in IPv6 address (:ffff::<ipv4>),
162then it will be treated as an IPv4 address. If you don't want that, you
163have to call C<parse_ipv4> and/or C<parse_ipv6> manually.
164
159=item $text = AnyEvent::Socket::aton $ipn 165=item $ipn = AnyEvent::Socket::aton $ip
160 166
161Same as C<parse_address>, but not exported (think C<Socket::inet_aton> but 167Same as C<parse_address>, but not exported (think C<Socket::inet_aton> but
162I<without> name resolution). 168I<without> name resolution).
163 169
164=cut 170=cut
165 171
166sub parse_address($) { 172sub parse_address($) {
167 &parse_ipv4 || &parse_ipv6 || &parse_unix 173 for (&parse_ipv6) {
174 if ($_) {
175 s/^\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff//;
176 return $_;
177 } else {
178 return &parse_ipv4 || &parse_unix
179 }
180 }
168} 181}
169 182
170*aton = \&parse_address; 183*aton = \&parse_address;
184
185=item ($name, $aliases, $proto) = getprotobyname $name
186
187Works like the builtin function of the same name, except it tries hard to
188work even on broken platforms (well, that's windows), where getprotobyname
189is traditionally very unreliable.
190
191=cut
192
193# microsoft can't even get getprotobyname working (the etc/protocols file
194# gets lost fairly often on windows), so we have to hardcode some common
195# protocol numbers ourselves.
196our %PROTO_BYNAME;
197
198$PROTO_BYNAME{tcp} = Socket::IPPROTO_TCP () if defined &Socket::IPPROTO_TCP;
199$PROTO_BYNAME{udp} = Socket::IPPROTO_UDP () if defined &Socket::IPPROTO_UDP;
200$PROTO_BYNAME{icmp} = Socket::IPPROTO_ICMP() if defined &Socket::IPPROTO_ICMP;
201
202sub getprotobyname($) {
203 my $name = lc shift;
204
205 defined (my $proton = $PROTO_BYNAME{$name} || (getprotobyname $name)[2])
206 or return;
207
208 ($name, uc $name, $proton)
209}
171 210
172=item ($host, $service) = parse_hostport $string[, $default_service] 211=item ($host, $service) = parse_hostport $string[, $default_service]
173 212
174Splitting a string of the form C<hostname:port> is a common 213Splitting a string of the form C<hostname:port> is a common
175problem. Unfortunately, just splitting on the colon makes it hard to 214problem. Unfortunately, just splitting on the colon makes it hard to
259 : 16 == length $_[0] 298 : 16 == length $_[0]
260 ? AF_INET6 299 ? AF_INET6
261 : unpack "S", $_[0] 300 : unpack "S", $_[0]
262} 301}
263 302
303=item $text = format_ipv4 $ipn
304
305Expects a four octet string representing a binary IPv4 address and returns
306its textual format. Rarely used, see C<format_address> for a nicer
307interface.
308
309=item $text = format_ipv6 $ipn
310
311Expects a sixteen octet string representing a binary IPv6 address and
312returns its textual format. Rarely used, see C<format_address> for a
313nicer interface.
314
264=item $text = format_address $ipn 315=item $text = format_address $ipn
265 316
266Covnvert a host address in network format (e.g. 4 octets for IPv4 or 16 317Covnvert a host address in network format (e.g. 4 octets for IPv4 or 16
267octets for IPv6) and convert it into textual form. 318octets for IPv6) and convert it into textual form.
268 319
271This function works similarly to C<inet_ntop AF_INET || AF_INET6, ...>, 322This function works similarly to C<inet_ntop AF_INET || AF_INET6, ...>,
272except it automatically detects the address type. 323except it automatically detects the address type.
273 324
274Returns C<undef> if it cannot detect the type. 325Returns C<undef> if it cannot detect the type.
275 326
327If the C<$ipn> is a mapped IPv4 in IPv6 address (:ffff::<ipv4>), then just
328the contained IPv4 address will be returned. If you do not want that, you
329have to call C<format_ipv6> manually.
330
276=item $text = AnyEvent::Socket::ntoa $ipn 331=item $text = AnyEvent::Socket::ntoa $ipn
277 332
278Same as format_address, but not exported (think C<inet_ntoa>). 333Same as format_address, but not exported (think C<inet_ntoa>).
279 334
280=cut 335=cut
281 336
282sub format_address; 337sub format_ipv4($) {
338 join ".", unpack "C4", $_[0]
339}
340
341sub format_ipv6($) {
342 if (v0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 eq $_[0]) {
343 return "::";
344 } elsif (v0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1 eq $_[0]) {
345 return "::1";
346 } elsif (v0.0.0.0.0.0.0.0.0.0.0.0 eq substr $_[0], 0, 12) {
347 # v4compatible
348 return "::" . format_ipv4 substr $_[0], 12;
349 } elsif (v0.0.0.0.0.0.0.0.0.0.255.255 eq substr $_[0], 0, 12) {
350 # v4mapped
351 return "::ffff:" . format_ipv4 substr $_[0], 12;
352 } elsif (v0.0.0.0.0.0.0.0.255.255.0.0 eq substr $_[0], 0, 12) {
353 # v4translated
354 return "::ffff:0:" . format_ipv4 substr $_[0], 12;
355 } else {
356 my $ip = sprintf "%x:%x:%x:%x:%x:%x:%x:%x", unpack "n8", $_[0];
357
358 # this is rather sucky, I admit
359 $ip =~ s/^0:(?:0:)*(0$)?/::/
360 or $ip =~ s/(:0){7}$/::/ or $ip =~ s/(:0){7}/:/
361 or $ip =~ s/(:0){6}$/::/ or $ip =~ s/(:0){6}/:/
362 or $ip =~ s/(:0){5}$/::/ or $ip =~ s/(:0){5}/:/
363 or $ip =~ s/(:0){4}$/::/ or $ip =~ s/(:0){4}/:/
364 or $ip =~ s/(:0){3}$/::/ or $ip =~ s/(:0){3}/:/
365 or $ip =~ s/(:0){2}$/::/ or $ip =~ s/(:0){2}/:/
366 or $ip =~ s/(:0){1}$/::/ or $ip =~ s/(:0){1}/:/;
367 return $ip
368 }
369}
370
283sub format_address($) { 371sub format_address($) {
284 my $af = address_family $_[0]; 372 my $af = address_family $_[0];
285 if ($af == AF_INET) { 373 if ($af == AF_INET) {
286 return join ".", unpack "C4", $_[0] 374 return &format_ipv4;
287 } elsif ($af == AF_INET6) { 375 } elsif ($af == AF_INET6) {
288 if (v0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 eq $_[0]) {
289 return "::";
290 } elsif (v0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1 eq $_[0]) {
291 return "::1";
292 } elsif (v0.0.0.0.0.0.0.0.0.0.0.0 eq substr $_[0], 0, 12) {
293 # v4compatible
294 return "::" . format_address substr $_[0], 12;
295 } elsif (v0.0.0.0.0.0.0.0.0.0.255.255 eq substr $_[0], 0, 12) { 376 return (v0.0.0.0.0.0.0.0.0.0.255.255 eq substr $_[0], 0, 12)
296 # v4mapped 377 ? format_ipv4 substr $_[0], 12
297 return "::ffff:" . format_address substr $_[0], 12; 378 : &format_ipv6;
298 } elsif (v0.0.0.0.0.0.0.0.255.255.0.0 eq substr $_[0], 0, 12) {
299 # v4translated
300 return "::ffff:0:" . format_address substr $_[0], 12;
301 } else {
302 my $ip = sprintf "%x:%x:%x:%x:%x:%x:%x:%x", unpack "n8", $_[0];
303
304 # this is rather sucky, I admit
305 $ip =~ s/^0:(?:0:)*(0$)?/::/
306 or $ip =~ s/(:0){7}$/::/ or $ip =~ s/(:0){7}/:/
307 or $ip =~ s/(:0){6}$/::/ or $ip =~ s/(:0){6}/:/
308 or $ip =~ s/(:0){5}$/::/ or $ip =~ s/(:0){5}/:/
309 or $ip =~ s/(:0){4}$/::/ or $ip =~ s/(:0){4}/:/
310 or $ip =~ s/(:0){3}$/::/ or $ip =~ s/(:0){3}/:/
311 or $ip =~ s/(:0){2}$/::/ or $ip =~ s/(:0){2}/:/
312 or $ip =~ s/(:0){1}$/::/ or $ip =~ s/(:0){1}/:/;
313 return $ip
314 }
315 } elsif ($af == AF_UNIX) { 379 } elsif ($af == AF_UNIX) {
316 return "unix/" 380 return "unix/"
317 } else { 381 } else {
318 return undef 382 return undef
319 } 383 }
462 526
463 resolve_sockaddr "google.com", "http", 0, undef, undef, sub { ... }; 527 resolve_sockaddr "google.com", "http", 0, undef, undef, sub { ... };
464 528
465=cut 529=cut
466 530
467# microsoft can't even get getprotobyname working (the etc/protocols file
468# gets lost fairly often on windows), so we have to hardcode some common
469# protocol numbers ourselves.
470our %PROTO_BYNAME;
471
472$PROTO_BYNAME{tcp} = &Socket::IPPROTO_TCP if defined &Socket::IPPROTO_TCP;
473$PROTO_BYNAME{udp} = &Socket::IPPROTO_UDP if defined &Socket::IPPROTO_UDP;
474$PROTO_BYNAME{icmp} = &Socket::IPPROTO_ICMP if defined &Socket::IPPROTO_ICMP;
475
476sub resolve_sockaddr($$$$$$) { 531sub resolve_sockaddr($$$$$$) {
477 my ($node, $service, $proto, $family, $type, $cb) = @_; 532 my ($node, $service, $proto, $family, $type, $cb) = @_;
478 533
479 if ($node eq "unix/") { 534 if ($node eq "unix/") {
480 return $cb->() if $family || $service !~ /^\//; # no can do 535 return $cb->() if $family || $service !~ /^\//; # no can do
496 $family ||= 6 unless $AnyEvent::PROTOCOL{ipv4}; 551 $family ||= 6 unless $AnyEvent::PROTOCOL{ipv4};
497 552
498 $proto ||= "tcp"; 553 $proto ||= "tcp";
499 $type ||= $proto eq "udp" ? SOCK_DGRAM : SOCK_STREAM; 554 $type ||= $proto eq "udp" ? SOCK_DGRAM : SOCK_STREAM;
500 555
501 my $proton = $PROTO_BYNAME{lc $proto} || (getprotobyname $proto)[2] 556 my $proton = getprotobyname $proto
502 or Carp::croak "$proto: protocol unknown"; 557 or Carp::croak "$proto: protocol unknown";
503 558
504 my $port; 559 my $port;
505 560
506 if ($service =~ /^(\S+)=(\d+)$/) { 561 if ($service =~ /^(\S+)=(\d+)$/) {
675 or die "unable to connect: $!"; 730 or die "unable to connect: $!";
676 731
677 my $handle; # avoid direct assignment so on_eof has it in scope. 732 my $handle; # avoid direct assignment so on_eof has it in scope.
678 $handle = new AnyEvent::Handle 733 $handle = new AnyEvent::Handle
679 fh => $fh, 734 fh => $fh,
735 on_error => sub {
736 warn "error $_[2]\n";
737 $_[0]->destroy;
738 },
680 on_eof => sub { 739 on_eof => sub {
681 undef $handle; # keep it alive till eof 740 $handle->destroy; # destroy handle
682 warn "done.\n"; 741 warn "done.\n";
683 }; 742 };
684 743
685 $handle->push_write ("GET / HTTP/1.0\015\012\015\012"); 744 $handle->push_write ("GET / HTTP/1.0\015\012\015\012");
686 745
725 784
726 $state{next} = sub { 785 $state{next} = sub {
727 return unless exists $state{fh}; 786 return unless exists $state{fh};
728 787
729 my $target = shift @target 788 my $target = shift @target
730 or do {
731 %state = ();
732 return $connect->(); 789 or return (%state = (), $connect->());
733 };
734 790
735 my ($domain, $type, $proto, $sockaddr) = @$target; 791 my ($domain, $type, $proto, $sockaddr) = @$target;
736 792
737 # socket creation 793 # socket creation
738 socket $state{fh}, $domain, $type, $proto 794 socket $state{fh}, $domain, $type, $proto
743 my $timeout = $prepare && $prepare->($state{fh}); 799 my $timeout = $prepare && $prepare->($state{fh});
744 800
745 $timeout ||= 30 if AnyEvent::WIN32; 801 $timeout ||= 30 if AnyEvent::WIN32;
746 802
747 $state{to} = AnyEvent->timer (after => $timeout, cb => sub { 803 $state{to} = AnyEvent->timer (after => $timeout, cb => sub {
748 $! = &Errno::ETIMEDOUT; 804 $! = Errno::ETIMEDOUT;
749 $state{next}(); 805 $state{next}();
750 }) if $timeout; 806 }) if $timeout;
751 807
752 # called when the connect was successful, which, 808 # called when the connect was successful, which,
753 # in theory, could be the case immediately (but never is in practise) 809 # in theory, could be the case immediately (but never is in practise)
754 $state{connected} = sub { 810 $state{connected} = sub {
755 delete $state{ww};
756 delete $state{to};
757
758 # we are connected, or maybe there was an error 811 # we are connected, or maybe there was an error
759 if (my $sin = getpeername $state{fh}) { 812 if (my $sin = getpeername $state{fh}) {
760 my ($port, $host) = unpack_sockaddr $sin; 813 my ($port, $host) = unpack_sockaddr $sin;
814
815 delete $state{ww}; delete $state{to};
761 816
762 my $guard = guard { %state = () }; 817 my $guard = guard { %state = () };
763 818
764 $connect->(delete $state{fh}, format_address $host, $port, sub { 819 $connect->(delete $state{fh}, format_address $host, $port, sub {
765 $guard->cancel; 820 $guard->cancel;
766 $state{next}(); 821 $state{next}();
767 }); 822 });
768 } else { 823 } else {
769 # dummy read to fetch real error code 824 # dummy read to fetch real error code
770 sysread $state{fh}, my $buf, 1 if $! == &Errno::ENOTCONN; 825 sysread $state{fh}, my $buf, 1 if $! == Errno::ENOTCONN;
826
827 return if $! == Errno::EAGAIN; # skip spurious wake-ups
828
829 delete $state{ww}; delete $state{to};
830
771 $state{next}(); 831 $state{next}();
772 } 832 }
773 }; 833 };
774 834
775 # now connect 835 # now connect
776 if (connect $state{fh}, $sockaddr) { 836 if (connect $state{fh}, $sockaddr) {
777 $state{connected}->(); 837 $state{connected}->();
778 } elsif ($! == &Errno::EINPROGRESS # POSIX 838 } elsif ($! == Errno::EINPROGRESS # POSIX
779 || $! == &Errno::EWOULDBLOCK 839 || $! == Errno::EWOULDBLOCK
780 # WSAEINPROGRESS intentionally not checked - it means something else entirely 840 # WSAEINPROGRESS intentionally not checked - it means something else entirely
781 || $! == AnyEvent::Util::WSAEINVAL # not convinced, but doesn't hurt 841 || $! == AnyEvent::Util::WSAEINVAL # not convinced, but doesn't hurt
782 || $! == AnyEvent::Util::WSAEWOULDBLOCK) { 842 || $! == AnyEvent::Util::WSAEWOULDBLOCK) {
783 $state{ww} = AnyEvent->io (fh => $state{fh}, poll => 'w', cb => $state{connected}); 843 $state{ww} = AnyEvent->io (fh => $state{fh}, poll => 'w', cb => $state{connected});
784 } else { 844 } else {
785 $state{next}(); 845 $state{next}();
786 } 846 }
787 }; 847 };
788 848
789 $! = &Errno::ENXIO; 849 $! = Errno::ENXIO;
790 $state{next}(); 850 $state{next}();
791 }; 851 };
792 852
793 defined wantarray && guard { %state = () } 853 defined wantarray && guard { %state = () }
794} 854}

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines