1 |
root |
1.1 |
=head1 NAME |
2 |
|
|
|
3 |
|
|
AnyEvent::Util - various utility functions. |
4 |
|
|
|
5 |
|
|
=head1 SYNOPSIS |
6 |
|
|
|
7 |
|
|
use AnyEvent::Util; |
8 |
|
|
|
9 |
root |
1.4 |
inet_aton $name, $cb->($ipn || undef); |
10 |
root |
1.1 |
|
11 |
|
|
=head1 DESCRIPTION |
12 |
|
|
|
13 |
|
|
This module implements various utility functions, mostly replacing |
14 |
|
|
well-known functions by event-ised counterparts. |
15 |
|
|
|
16 |
|
|
=over 4 |
17 |
|
|
|
18 |
|
|
=cut |
19 |
|
|
|
20 |
|
|
package AnyEvent::Util; |
21 |
|
|
|
22 |
|
|
use strict; |
23 |
|
|
|
24 |
|
|
no warnings "uninitialized"; |
25 |
|
|
|
26 |
|
|
use Socket (); |
27 |
|
|
|
28 |
|
|
use AnyEvent; |
29 |
|
|
|
30 |
|
|
use base 'Exporter'; |
31 |
|
|
|
32 |
|
|
#our @EXPORT = qw(gethostbyname gethostbyaddr); |
33 |
root |
1.4 |
our @EXPORT_OK = qw(inet_aton); |
34 |
root |
1.1 |
|
35 |
|
|
our $VERSION = '1.0'; |
36 |
|
|
|
37 |
|
|
our $MAXPARALLEL = 16; # max. number of parallel jobs |
38 |
|
|
|
39 |
|
|
our $running; |
40 |
|
|
our @queue; |
41 |
|
|
|
42 |
|
|
sub _schedule; |
43 |
|
|
sub _schedule { |
44 |
|
|
return unless @queue; |
45 |
|
|
return if $running >= $MAXPARALLEL; |
46 |
|
|
|
47 |
|
|
++$running; |
48 |
|
|
my ($cb, $sub, @args) = @{shift @queue}; |
49 |
|
|
|
50 |
root |
1.2 |
if (eval { local $SIG{__DIE__}; require POSIX }) { |
51 |
root |
1.1 |
my $pid = open my $fh, "-|"; |
52 |
|
|
|
53 |
|
|
if (!defined $pid) { |
54 |
|
|
die "fork: $!"; |
55 |
|
|
} elsif (!$pid) { |
56 |
|
|
syswrite STDOUT, join "\0", map { unpack "H*", $_ } $sub->(@args); |
57 |
|
|
POSIX::_exit (0); |
58 |
|
|
} |
59 |
|
|
|
60 |
|
|
my $w; $w = AnyEvent->io (fh => $fh, poll => 'r', cb => sub { |
61 |
|
|
--$running; |
62 |
|
|
_schedule; |
63 |
|
|
undef $w; |
64 |
|
|
|
65 |
|
|
my $buf; |
66 |
|
|
sysread $fh, $buf, 16384, length $buf; |
67 |
|
|
$cb->(map { pack "H*", $_ } split /\0/, $buf); |
68 |
|
|
}); |
69 |
|
|
} else { |
70 |
|
|
$cb->($sub->(@args)); |
71 |
|
|
} |
72 |
|
|
} |
73 |
|
|
|
74 |
|
|
sub _do_asy { |
75 |
|
|
push @queue, [@_]; |
76 |
|
|
_schedule; |
77 |
|
|
} |
78 |
|
|
|
79 |
|
|
sub dotted_quad($) { |
80 |
|
|
$_[0] =~ /^(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0-9][0-9]?) |
81 |
|
|
\.(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0-9][0-9]?) |
82 |
|
|
\.(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0-9][0-9]?) |
83 |
|
|
\.(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0-9][0-9]?)$/x |
84 |
|
|
} |
85 |
|
|
|
86 |
|
|
my $has_ev_adns; |
87 |
|
|
|
88 |
|
|
sub has_ev_adns { |
89 |
|
|
($has_ev_adns ||= do { |
90 |
|
|
my $model = AnyEvent::detect; |
91 |
|
|
(($model eq "AnyEvent::Impl::CoroEV" or $model eq "AnyEvent::Impl::EV") |
92 |
root |
1.3 |
&& eval { local $SIG{__DIE__}; require EV::ADNS }) |
93 |
|
|
? 2 : 1 # so that || always detects as true |
94 |
|
|
}) - 1 # 2 => true, 1 => false |
95 |
root |
1.1 |
} |
96 |
|
|
|
97 |
|
|
=item AnyEvent::Util::inet_aton $name_or_address, $cb->($binary_address_or_undef) |
98 |
|
|
|
99 |
|
|
Works almost exactly like its Socket counterpart, except that it uses a |
100 |
|
|
callback. |
101 |
|
|
|
102 |
|
|
=cut |
103 |
|
|
|
104 |
|
|
sub inet_aton { |
105 |
|
|
my ($name, $cb) = @_; |
106 |
|
|
|
107 |
|
|
if (&dotted_quad) { |
108 |
|
|
$cb->(Socket::inet_aton $name); |
109 |
root |
1.6 |
} elsif ($name eq "localhost") { # rfc2606 et al. |
110 |
|
|
$cb->(v127.0.0.1); |
111 |
root |
1.4 |
} elsif (&has_ev_adns) { |
112 |
root |
1.5 |
EV::ADNS::submit ($name, &EV::ADNS::r_addr, 0, sub { |
113 |
root |
1.4 |
my (undef, undef, @a) = @_; |
114 |
root |
1.1 |
$cb->(@a ? Socket::inet_aton $a[0] : undef); |
115 |
|
|
}); |
116 |
|
|
} else { |
117 |
|
|
_do_asy $cb, sub { Socket::inet_aton $_[0] }, @_; |
118 |
|
|
} |
119 |
|
|
} |
120 |
|
|
|
121 |
root |
1.6 |
=item AnyEvent::Util::fh_nonblocking $fh, $nonblocking |
122 |
|
|
|
123 |
|
|
Sets the blocking state of the given filehandle (true == nonblocking, |
124 |
|
|
false == blocking). Uses fcntl on anything sensible and ioctl FIONBIO on |
125 |
|
|
broken (i.e. windows) platforms. |
126 |
|
|
|
127 |
|
|
=cut |
128 |
|
|
|
129 |
|
|
sub fh_nonblocking($$) { |
130 |
|
|
my ($fh, $nb) = @_; |
131 |
|
|
|
132 |
|
|
require Fcntl; |
133 |
|
|
|
134 |
|
|
if ($^O eq "MSWin32") { |
135 |
|
|
$nb = (! ! $nb) + 0; |
136 |
|
|
ioctl $fh, 0x8004667e, \$nb; # FIONBIO |
137 |
|
|
} else { |
138 |
|
|
fcntl $fh, &Fcntl::F_SETFL, $nb ? &Fcntl::O_NONBLOCK : 0; |
139 |
|
|
} |
140 |
|
|
} |
141 |
|
|
|
142 |
root |
1.1 |
1; |
143 |
|
|
|
144 |
|
|
=back |
145 |
|
|
|
146 |
|
|
=head1 AUTHOR |
147 |
|
|
|
148 |
|
|
Marc Lehmann <schmorp@schmorp.de> |
149 |
|
|
http://home.schmorp.de/ |
150 |
|
|
|
151 |
|
|
=cut |
152 |
|
|
|