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.8 by root, Fri May 23 17:50:15 2008 UTC vs.
Revision 1.11 by root, Fri May 23 20:09:56 2008 UTC

39 39
40our @EXPORT = qw(inet_aton tcp_server tcp_connect); 40our @EXPORT = qw(inet_aton tcp_server tcp_connect);
41 41
42our $VERSION = '1.0'; 42our $VERSION = '1.0';
43 43
44sub dotted_quad($) { 44=item $ipn = parse_ipv4 $dotted_quad
45 $_[0] =~ /^(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0-9][0-9]?) 45
46 \.(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0-9][0-9]?) 46Tries to parse the given dotted quad IPv4 address and return it in
47 \.(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0-9][0-9]?) 47octet form (or undef when it isn't in a parsable format). Supports all
48 \.(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0-9][0-9]?)$/x 48forms specified by POSIX (e.g. C<10.0.0.1>, C<10.1>, C<10.0x020304>,
49C<0x12345678> or C<0377.0377.0377.0377>).
50
51=cut
52
53sub parse_ipv4($) {
54 $_[0] =~ /^ (?: 0x[0-9a-fA-F]+ | 0[0-7]* | [1-9][0-9]* )
55 (?:\. (?: 0x[0-9a-fA-F]+ | 0[0-7]* | [1-9][0-9]* ) ){0,3}$/x
56 or return undef;
57
58 @_ = map /^0/ ? oct : $_, split /\./, $_[0];
59
60 # check leading parts against range
61 return undef if grep $_ >= 256, @_[0 .. @_ - 2];
62
63 # check trailing part against range
64 return undef if $_[-1] >= 1 << (8 * (4 - $#_));
65
66 pack "N", (pop)
67 + ($_[0] << 24)
68 + ($_[1] << 16)
69 + ($_[2] << 8);
70}
71
72=item $ipn = parse_ipv4 $dotted_quad
73
74Tries to parse the given IPv6 address and return it in
75octet form (or undef when it isn't in a parsable format).
76
77Should support all forms specified by RFC 2373 (and additionally all IPv4
78formst supported by parse_ipv4).
79
80=cut
81
82sub parse_ipv6($) {
83 # quick test to avoid longer processing
84 my $n = $_[0] =~ y/://;
85 return undef if $n < 2 || $n > 8;
86
87 my ($h, $t) = split /::/, $_[0], 2;
88
89 unless (defined $t) {
90 ($h, $t) = (undef, $h);
91 }
92
93 my @h = split /:/, $h;
94 my @t = split /:/, $t;
95
96 # check four ipv4 tail
97 if (@t && $t[-1]=~ /\./) {
98 return undef if $n > 6;
99
100 my $ipn = parse_ipv4 pop @t
101 or return undef;
102
103 push @t, map +(sprintf "%x", $_), unpack "nn", $ipn;
104 }
105
106 # no :: then we need to have exactly 8 components
107 return undef unless @h + @t == 8 || $_[0] =~ /::/;
108
109 # now check all parts for validity
110 return undef if grep !/^[0-9a-fA-F]{1,4}$/, @h, @t;
111
112 # now pad...
113 push @h, 0 while @h + @t < 8;
114
115 # and done
116 pack "n*", map hex, @h, @t
117}
118
119=item $ipn = parse_ip $text
120
121Combines C<parse_ipv4> and C<parse_ipv6> in one function.
122
123=cut
124
125sub parse_ip($) {
126 &parse_ipv4 || &parse_ipv6
127}
128
129=item $text = format_ip $ipn
130
131Takes either an IPv4 address (4 octets) or and IPv6 address (16 octets)
132and converts it into textual form.
133
134=cut
135
136sub format_ip;
137sub format_ip($) {
138 if (4 == length $_[0]) {
139 return join ".", unpack "C4", $_[0]
140 } elsif (16 == length $_[0]) {
141 if (v0.0.0.0.0.0.0.0.0.0.255.255 eq substr $_[0], 0, 12) {
142 # v4mapped
143 return "::ffff:" . format_ip substr $_[0], 12;
144 } else {
145 my $ip = sprintf "%x:%x:%x:%x:%x:%x:%x:%x", unpack "n8", $_[0];
146
147 $ip =~ s/^0:(?:0:)*/::/
148 or $ip =~ s/(:0)+$/::/
149 or $ip =~ s/(:0)+/:/;
150 return $ip
151 }
152 } else {
153 return undef
154 }
49} 155}
50 156
51=item inet_aton $name_or_address, $cb->(@addresses) 157=item inet_aton $name_or_address, $cb->(@addresses)
52 158
53Works similarly to its Socket counterpart, except that it uses a 159Works similarly to its Socket counterpart, except that it uses a
61=cut 167=cut
62 168
63sub inet_aton { 169sub inet_aton {
64 my ($name, $cb) = @_; 170 my ($name, $cb) = @_;
65 171
66 if (&dotted_quad) { 172 if (my $ipn = &parse_ipv4) {
67 $cb->(socket_inet_aton $name); 173 $cb->($ipn);
174 } elsif (my $ipn = &parse_ipv6) {
175 $cb->($ipn);
68 } elsif ($name eq "localhost") { # rfc2606 et al. 176 } elsif ($name eq "localhost") { # rfc2606 et al.
69 $cb->(v127.0.0.1); 177 $cb->(v127.0.0.1, v0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1);
70 } else { 178 } else {
71 require AnyEvent::DNS; 179 require AnyEvent::DNS;
72 180
73 # simple, bad suboptimal algorithm 181 # simple, bad suboptimal algorithm
74 AnyEvent::DNS::a ($name, sub { 182 AnyEvent::DNS::a ($name, sub {
75 if (@_) { 183 if (@_) {
76 $cb->(map +(socket_inet_aton $_), @_); 184 $cb->(map +(parse_ipv4 $_), @_);
77 } else { 185 } else {
78 $cb->(); 186 $cb->();
79 #AnyEvent::DNS::aaaa ($name, $cb); need inet_pton 187 #AnyEvent::DNS::aaaa ($name, $cb); need inet_pton
80 } 188 }
81 }); 189 });

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines