| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
# You may distribute under the terms of either the GNU General Public License |
|
2
|
|
|
|
|
|
|
# or the Artistic License (the same terms as Perl itself) |
|
3
|
|
|
|
|
|
|
# |
|
4
|
|
|
|
|
|
|
# (C) Paul Evans, 2007-2021 -- leonerd@leonerd.org.uk |
|
5
|
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
package IO::Async::Resolver; |
|
7
|
|
|
|
|
|
|
|
|
8
|
7
|
|
|
7
|
|
940
|
use strict; |
|
|
7
|
|
|
|
|
11
|
|
|
|
7
|
|
|
|
|
193
|
|
|
9
|
7
|
|
|
7
|
|
31
|
use warnings; |
|
|
7
|
|
|
|
|
40
|
|
|
|
7
|
|
|
|
|
228
|
|
|
10
|
7
|
|
|
7
|
|
44
|
use base qw( IO::Async::Function ); |
|
|
7
|
|
|
|
|
12
|
|
|
|
7
|
|
|
|
|
3155
|
|
|
11
|
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
our $VERSION = '0.802'; |
|
13
|
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
# Socket 2.006 fails to getaddrinfo() AI_NUMERICHOST properly on MSWin32 |
|
15
|
7
|
|
|
|
|
453
|
use Socket 2.007 qw( |
|
16
|
|
|
|
|
|
|
AI_NUMERICHOST AI_PASSIVE |
|
17
|
|
|
|
|
|
|
NI_NUMERICHOST NI_NUMERICSERV NI_DGRAM |
|
18
|
|
|
|
|
|
|
EAI_NONAME |
|
19
|
7
|
|
|
7
|
|
42
|
); |
|
|
7
|
|
|
|
|
121
|
|
|
20
|
|
|
|
|
|
|
|
|
21
|
7
|
|
|
7
|
|
46
|
use IO::Async::Metrics '$METRICS'; |
|
|
7
|
|
|
|
|
24
|
|
|
|
7
|
|
|
|
|
49
|
|
|
22
|
7
|
|
|
7
|
|
37
|
use IO::Async::OS; |
|
|
7
|
|
|
|
|
11
|
|
|
|
7
|
|
|
|
|
387
|
|
|
23
|
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
# Try to use HiRes alarm, but we don't strictly need it. |
|
25
|
|
|
|
|
|
|
# MSWin32 doesn't implement it |
|
26
|
|
|
|
|
|
|
BEGIN { |
|
27
|
7
|
|
|
7
|
|
44
|
require Time::HiRes; |
|
28
|
7
|
50
|
|
|
|
10
|
eval { Time::HiRes::alarm(0) } and Time::HiRes->import( qw( alarm ) ); |
|
|
7
|
|
|
|
|
227
|
|
|
29
|
|
|
|
|
|
|
} |
|
30
|
|
|
|
|
|
|
|
|
31
|
7
|
|
|
7
|
|
38
|
use Carp; |
|
|
7
|
|
|
|
|
9
|
|
|
|
7
|
|
|
|
|
16980
|
|
|
32
|
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
my $started = 0; |
|
34
|
|
|
|
|
|
|
my %METHODS; |
|
35
|
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
=head1 NAME |
|
37
|
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
C - performing name resolutions asynchronously |
|
39
|
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
=head1 SYNOPSIS |
|
41
|
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
This object is used indirectly via an L: |
|
43
|
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
use IO::Async::Loop; |
|
45
|
|
|
|
|
|
|
my $loop = IO::Async::Loop->new; |
|
46
|
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
my @results = $loop->resolver->getaddrinfo( |
|
48
|
|
|
|
|
|
|
host => "www.example.com", |
|
49
|
|
|
|
|
|
|
service => "http", |
|
50
|
|
|
|
|
|
|
)->get; |
|
51
|
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
foreach my $addr ( @results ) { |
|
53
|
|
|
|
|
|
|
printf "http://www.example.com can be reached at " . |
|
54
|
|
|
|
|
|
|
"socket(%d,%d,%d) + connect('%v02x')\n", |
|
55
|
|
|
|
|
|
|
@{$addr}{qw( family socktype protocol addr )}; |
|
56
|
|
|
|
|
|
|
} |
|
57
|
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
my @pwent = $loop->resolve( type => 'getpwuid', data => [ $< ] )->get; |
|
59
|
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
print "My passwd ent: " . join( "|", @pwent ) . "\n"; |
|
61
|
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
63
|
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
This module extends an L to use the system's name resolver |
|
65
|
|
|
|
|
|
|
functions asynchronously. It provides a number of named resolvers, each one |
|
66
|
|
|
|
|
|
|
providing an asynchronous wrapper around a single resolver function. |
|
67
|
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
Because the system may not provide asynchronous versions of its resolver |
|
69
|
|
|
|
|
|
|
functions, this class is implemented using a L object |
|
70
|
|
|
|
|
|
|
that wraps the normal (blocking) functions. In this case, name resolutions |
|
71
|
|
|
|
|
|
|
will be performed asynchronously from the rest of the program, but will likely |
|
72
|
|
|
|
|
|
|
be done by a single background worker process, so will be processed in the |
|
73
|
|
|
|
|
|
|
order they were requested; a single slow lookup will hold up the queue of |
|
74
|
|
|
|
|
|
|
other requests behind it. To mitigate this, multiple worker processes can be |
|
75
|
|
|
|
|
|
|
used; see the C argument to the constructor. |
|
76
|
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
The C parameter for the underlying L object |
|
78
|
|
|
|
|
|
|
is set to a default of 30 seconds, and C is set to 0. This |
|
79
|
|
|
|
|
|
|
ensures that there are no spare processes sitting idle during the common case |
|
80
|
|
|
|
|
|
|
of no outstanding requests. |
|
81
|
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
=cut |
|
83
|
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
sub _init |
|
85
|
|
|
|
|
|
|
{ |
|
86
|
6
|
|
|
6
|
|
6
|
my $self = shift; |
|
87
|
6
|
|
|
|
|
12
|
my ( $params ) = @_; |
|
88
|
6
|
|
|
|
|
30
|
$self->SUPER::_init( @_ ); |
|
89
|
|
|
|
|
|
|
|
|
90
|
6
|
|
|
|
|
10
|
$params->{module} = __PACKAGE__; |
|
91
|
6
|
|
|
|
|
13
|
$params->{func} = "_resolve"; |
|
92
|
|
|
|
|
|
|
|
|
93
|
6
|
|
|
|
|
8
|
$params->{idle_timeout} = 30; |
|
94
|
6
|
|
|
|
|
11
|
$params->{min_workers} = 0; |
|
95
|
|
|
|
|
|
|
|
|
96
|
6
|
|
|
|
|
11
|
$started = 1; |
|
97
|
|
|
|
|
|
|
} |
|
98
|
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
sub _resolve |
|
100
|
|
|
|
|
|
|
{ |
|
101
|
0
|
|
|
0
|
|
0
|
my ( $type, $timeout, @data ) = @_; |
|
102
|
|
|
|
|
|
|
|
|
103
|
0
|
0
|
|
|
|
0
|
if( my $code = $METHODS{$type} ) { |
|
104
|
0
|
|
|
0
|
|
0
|
local $SIG{ALRM} = sub { die "Timed out\n" }; |
|
|
0
|
|
|
|
|
0
|
|
|
105
|
|
|
|
|
|
|
|
|
106
|
0
|
|
|
|
|
0
|
alarm( $timeout ); |
|
107
|
0
|
|
|
|
|
0
|
my @ret = eval { $code->( @data ) }; |
|
|
0
|
|
|
|
|
0
|
|
|
108
|
0
|
|
|
|
|
0
|
alarm( 0 ); |
|
109
|
|
|
|
|
|
|
|
|
110
|
0
|
0
|
|
|
|
0
|
die $@ if $@; |
|
111
|
0
|
|
|
|
|
0
|
return @ret; |
|
112
|
|
|
|
|
|
|
} |
|
113
|
|
|
|
|
|
|
else { |
|
114
|
0
|
|
|
|
|
0
|
die "Unrecognised resolver request '$type'"; |
|
115
|
|
|
|
|
|
|
} |
|
116
|
|
|
|
|
|
|
} |
|
117
|
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
sub debug_printf_call |
|
119
|
|
|
|
|
|
|
{ |
|
120
|
15
|
|
|
15
|
0
|
20
|
my $self = shift; |
|
121
|
15
|
|
|
|
|
36
|
my ( $type, undef, @data ) = @_; |
|
122
|
|
|
|
|
|
|
|
|
123
|
15
|
|
|
|
|
32
|
my $arg0; |
|
124
|
15
|
100
|
|
|
|
45
|
if( $type eq "getaddrinfo" ) { |
|
|
|
100
|
|
|
|
|
|
|
125
|
5
|
|
|
|
|
24
|
my %args = @data; |
|
126
|
5
|
|
|
|
|
28
|
$arg0 = sprintf "%s:%s", @args{qw( host service )}; |
|
127
|
|
|
|
|
|
|
} |
|
128
|
|
|
|
|
|
|
elsif( $type eq "getnameinfo" ) { |
|
129
|
|
|
|
|
|
|
# cheat |
|
130
|
3
|
|
|
|
|
12
|
$arg0 = sprintf "%s:%s", ( Socket::getnameinfo( $data[0], NI_NUMERICHOST|NI_NUMERICSERV ) )[1,2]; |
|
131
|
|
|
|
|
|
|
} |
|
132
|
|
|
|
|
|
|
else { |
|
133
|
7
|
|
|
|
|
11
|
$arg0 = $data[0]; |
|
134
|
|
|
|
|
|
|
} |
|
135
|
|
|
|
|
|
|
|
|
136
|
15
|
|
|
|
|
117
|
$self->debug_printf( "CALL $type $arg0" ); |
|
137
|
|
|
|
|
|
|
} |
|
138
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
sub debug_printf_result |
|
140
|
|
|
|
|
|
|
{ |
|
141
|
14
|
|
|
14
|
0
|
22
|
my $self = shift; |
|
142
|
14
|
|
|
|
|
40
|
my ( @result ) = @_; |
|
143
|
14
|
|
|
|
|
65
|
$self->debug_printf( "RESULT n=" . scalar @result ); |
|
144
|
|
|
|
|
|
|
} |
|
145
|
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
=head1 METHODS |
|
147
|
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
The following methods documented with a trailing call to C<< ->get >> return |
|
149
|
|
|
|
|
|
|
L instances. |
|
150
|
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
=cut |
|
152
|
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
=head2 resolve |
|
154
|
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
@result = $loop->resolve( %params )->get |
|
156
|
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
Performs a single name resolution operation, as given by the keys in the hash. |
|
158
|
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
The C<%params> hash keys the following keys: |
|
160
|
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
=over 8 |
|
162
|
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
=item type => STRING |
|
164
|
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
Name of the resolution operation to perform. See BUILT-IN RESOLVERS for the |
|
166
|
|
|
|
|
|
|
list of available operations. |
|
167
|
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
=item data => ARRAY |
|
169
|
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
Arguments to pass to the resolver function. Exact meaning depends on the |
|
171
|
|
|
|
|
|
|
specific function chosen by the C; see BUILT-IN RESOLVERS. |
|
172
|
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
=item timeout => NUMBER |
|
174
|
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
Optional. Timeout in seconds, after which the resolver operation will abort |
|
176
|
|
|
|
|
|
|
with a timeout exception. If not supplied, a default of 10 seconds will apply. |
|
177
|
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
=back |
|
179
|
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
On failure, the fail category name is C; the details give the |
|
181
|
|
|
|
|
|
|
individual resolver function name (e.g. C), followed by other |
|
182
|
|
|
|
|
|
|
error details specific to the resolver in question. |
|
183
|
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
->fail( $message, resolve => $type => @details ) |
|
185
|
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
=head2 resolve (void) |
|
187
|
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
$resolver->resolve( %params ) |
|
189
|
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
When not returning a future, additional parameters can be given containing the |
|
191
|
|
|
|
|
|
|
continuations to invoke on success or failure: |
|
192
|
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
=over 8 |
|
194
|
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
=item on_resolved => CODE |
|
196
|
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
A continuation that is invoked when the resolver function returns a successful |
|
198
|
|
|
|
|
|
|
result. It will be passed the array returned by the resolver function. |
|
199
|
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
$on_resolved->( @result ) |
|
201
|
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
=item on_error => CODE |
|
203
|
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
A continuation that is invoked when the resolver function fails. It will be |
|
205
|
|
|
|
|
|
|
passed the exception thrown by the function. |
|
206
|
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
=back |
|
208
|
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
=cut |
|
210
|
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
sub resolve |
|
212
|
|
|
|
|
|
|
{ |
|
213
|
15
|
|
|
15
|
1
|
7503
|
my $self = shift; |
|
214
|
15
|
|
|
|
|
68
|
my %args = @_; |
|
215
|
|
|
|
|
|
|
|
|
216
|
15
|
|
|
|
|
28
|
my $type = $args{type}; |
|
217
|
15
|
50
|
|
|
|
31
|
defined $type or croak "Expected 'type'"; |
|
218
|
|
|
|
|
|
|
|
|
219
|
15
|
100
|
|
|
|
32
|
if( $type eq "getaddrinfo_hash" ) { |
|
220
|
1
|
|
|
|
|
9
|
$type = "getaddrinfo"; |
|
221
|
|
|
|
|
|
|
} |
|
222
|
|
|
|
|
|
|
|
|
223
|
15
|
50
|
|
|
|
33
|
exists $METHODS{$type} or croak "Expected 'type' to be an existing resolver method, got '$type'"; |
|
224
|
|
|
|
|
|
|
|
|
225
|
15
|
|
|
|
|
18
|
my $on_resolved; |
|
226
|
15
|
100
|
|
|
|
35
|
if( $on_resolved = $args{on_resolved} ) { |
|
|
|
50
|
|
|
|
|
|
|
227
|
7
|
50
|
|
|
|
17
|
ref $on_resolved or croak "Expected 'on_resolved' to be a reference"; |
|
228
|
|
|
|
|
|
|
} |
|
229
|
|
|
|
|
|
|
elsif( !defined wantarray ) { |
|
230
|
0
|
|
|
|
|
0
|
croak "Expected 'on_resolved' or to return a Future"; |
|
231
|
|
|
|
|
|
|
} |
|
232
|
|
|
|
|
|
|
|
|
233
|
15
|
|
|
|
|
16
|
my $on_error; |
|
234
|
15
|
100
|
|
|
|
36
|
if( $on_error = $args{on_error} ) { |
|
|
|
50
|
|
|
|
|
|
|
235
|
7
|
50
|
|
|
|
13
|
ref $on_error or croak "Expected 'on_error' to be a reference"; |
|
236
|
|
|
|
|
|
|
} |
|
237
|
|
|
|
|
|
|
elsif( !defined wantarray ) { |
|
238
|
0
|
|
|
|
|
0
|
croak "Expected 'on_error' or to return a Future"; |
|
239
|
|
|
|
|
|
|
} |
|
240
|
|
|
|
|
|
|
|
|
241
|
15
|
|
50
|
|
|
58
|
my $timeout = $args{timeout} || 10; |
|
242
|
|
|
|
|
|
|
|
|
243
|
15
|
100
|
|
|
|
61
|
$METRICS and $METRICS->inc_counter( resolver_lookups => [ type => $type ] ); |
|
244
|
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
my $future = $self->call( |
|
246
|
15
|
|
|
|
|
56
|
args => [ $type, $timeout, @{$args{data}} ], |
|
247
|
|
|
|
|
|
|
)->else( sub { |
|
248
|
1
|
|
|
1
|
|
28
|
my ( $message, @detail ) = @_; |
|
249
|
1
|
50
|
|
|
|
4
|
$METRICS and $METRICS->inc_counter( resolver_failures => [ type => $type ] ); |
|
250
|
1
|
|
|
|
|
79
|
Future->fail( $message, resolve => $type => @detail ); |
|
251
|
15
|
|
|
|
|
1043
|
}); |
|
252
|
|
|
|
|
|
|
|
|
253
|
15
|
100
|
|
|
|
524
|
$future->on_done( $on_resolved ) if $on_resolved; |
|
254
|
15
|
100
|
|
|
|
138
|
$future->on_fail( $on_error ) if $on_error; |
|
255
|
|
|
|
|
|
|
|
|
256
|
15
|
100
|
|
|
|
216
|
return $future if defined wantarray; |
|
257
|
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
# Caller is not going to keep hold of the Future, so we have to ensure it |
|
259
|
|
|
|
|
|
|
# stays alive somehow |
|
260
|
7
|
|
|
0
|
|
24
|
$self->adopt_future( $future->else( sub { Future->done } ) ); |
|
|
0
|
|
|
|
|
0
|
|
|
261
|
|
|
|
|
|
|
} |
|
262
|
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
=head2 getaddrinfo |
|
264
|
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
@addrs = $resolver->getaddrinfo( %args )->get |
|
266
|
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
A shortcut wrapper around the C resolver, taking its arguments in |
|
268
|
|
|
|
|
|
|
a more convenient form. |
|
269
|
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
=over 8 |
|
271
|
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
=item host => STRING |
|
273
|
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
=item service => STRING |
|
275
|
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
The host and service names to look up. At least one must be provided. |
|
277
|
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
=item family => INT or STRING |
|
279
|
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
=item socktype => INT or STRING |
|
281
|
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
=item protocol => INT |
|
283
|
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
Hint values used to filter the results. |
|
285
|
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
=item flags => INT |
|
287
|
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
Flags to control the C function. See the C constants in |
|
289
|
|
|
|
|
|
|
L's C function for more detail. |
|
290
|
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
=item passive => BOOL |
|
292
|
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
If true, sets the C flag. This is provided as a convenience to |
|
294
|
|
|
|
|
|
|
avoid the caller from having to import the C constant from |
|
295
|
|
|
|
|
|
|
C. |
|
296
|
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
=item timeout => NUMBER |
|
298
|
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
Time in seconds after which to abort the lookup with a C exception |
|
300
|
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
=back |
|
302
|
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
On success, the future will yield the result as a list of HASH references; |
|
304
|
|
|
|
|
|
|
each containing one result. Each result will contain fields called C, |
|
305
|
|
|
|
|
|
|
C, C and C. If requested by C then the |
|
306
|
|
|
|
|
|
|
C field will also be present. |
|
307
|
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
On failure, the detail field will give the error number, which should match |
|
309
|
|
|
|
|
|
|
one of the C constants. |
|
310
|
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
->fail( $message, resolve => getaddrinfo => $eai_errno ) |
|
312
|
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
As a specific optimisation, this method will try to perform a lookup of |
|
314
|
|
|
|
|
|
|
numeric values synchronously, rather than asynchronously, if it looks likely |
|
315
|
|
|
|
|
|
|
to succeed. |
|
316
|
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
Specifically, if the service name is entirely numeric, and the hostname looks |
|
318
|
|
|
|
|
|
|
like an IPv4 or IPv6 string, a synchronous lookup will first be performed |
|
319
|
|
|
|
|
|
|
using the C flag. If this gives an C error, then |
|
320
|
|
|
|
|
|
|
the lookup is performed asynchronously instead. |
|
321
|
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
=head2 getaddrinfo (void) |
|
323
|
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
$resolver->getaddrinfo( %args ) |
|
325
|
|
|
|
|
|
|
|
|
326
|
|
|
|
|
|
|
When not returning a future, additional parameters can be given containing the |
|
327
|
|
|
|
|
|
|
continuations to invoke on success or failure: |
|
328
|
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
=over 8 |
|
330
|
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
=item on_resolved => CODE |
|
332
|
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
Callback which is invoked after a successful lookup. |
|
334
|
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
$on_resolved->( @addrs ) |
|
336
|
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
=item on_error => CODE |
|
338
|
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
Callback which is invoked after a failed lookup, including for a timeout. |
|
340
|
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
$on_error->( $exception ) |
|
342
|
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
=back |
|
344
|
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
=cut |
|
346
|
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
sub getaddrinfo |
|
348
|
|
|
|
|
|
|
{ |
|
349
|
16
|
|
|
16
|
1
|
7660
|
my $self = shift; |
|
350
|
16
|
|
|
|
|
62
|
my %args = @_; |
|
351
|
|
|
|
|
|
|
|
|
352
|
|
|
|
|
|
|
$args{on_resolved} or defined wantarray or |
|
353
|
16
|
50
|
66
|
|
|
76
|
croak "Expected 'on_resolved' or to return a Future"; |
|
354
|
|
|
|
|
|
|
|
|
355
|
|
|
|
|
|
|
$args{on_error} or defined wantarray or |
|
356
|
16
|
50
|
66
|
|
|
65
|
croak "Expected 'on_error' or to return a Future"; |
|
357
|
|
|
|
|
|
|
|
|
358
|
16
|
|
100
|
|
|
67
|
my $host = $args{host} || ""; |
|
359
|
16
|
100
|
|
|
|
24
|
my $service = $args{service}; defined $service or $service = ""; |
|
|
16
|
|
|
|
|
30
|
|
|
360
|
16
|
|
50
|
|
|
59
|
my $flags = $args{flags} || 0; |
|
361
|
|
|
|
|
|
|
|
|
362
|
16
|
100
|
|
|
|
36
|
$flags |= AI_PASSIVE if $args{passive}; |
|
363
|
|
|
|
|
|
|
|
|
364
|
16
|
100
|
|
|
|
68
|
$args{family} = IO::Async::OS->getfamilybyname( $args{family} ) if defined $args{family}; |
|
365
|
16
|
50
|
|
|
|
95
|
$args{socktype} = IO::Async::OS->getsocktypebyname( $args{socktype} ) if defined $args{socktype}; |
|
366
|
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
# Clear any other existing but undefined hints |
|
368
|
16
|
|
66
|
|
|
97
|
defined $args{$_} or delete $args{$_} for keys %args; |
|
369
|
|
|
|
|
|
|
|
|
370
|
|
|
|
|
|
|
# It's likely this will succeed with AI_NUMERICHOST if host contains only |
|
371
|
|
|
|
|
|
|
# [\d.] (IPv4) or [[:xdigit:]:] (IPv6) |
|
372
|
|
|
|
|
|
|
# Technically we should pass AI_NUMERICSERV but not all platforms support |
|
373
|
|
|
|
|
|
|
# it, but since we're checking service contains only \d we should be fine. |
|
374
|
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
# These address tests don't have to be perfect as if it fails we'll get |
|
376
|
|
|
|
|
|
|
# EAI_NONAME and just try it asynchronously anyway |
|
377
|
16
|
100
|
100
|
|
|
162
|
if( ( $host =~ m/^[\d.]+$/ or $host =~ m/^[[:xdigit:]:]$/ or $host eq "" ) and |
|
|
|
|
66
|
|
|
|
|
|
378
|
|
|
|
|
|
|
$service =~ m/^\d*$/ ) { |
|
379
|
|
|
|
|
|
|
|
|
380
|
12
|
|
|
|
|
588
|
my ( $err, @results ) = Socket::getaddrinfo( $host, $service, |
|
381
|
|
|
|
|
|
|
{ %args, flags => $flags | AI_NUMERICHOST } |
|
382
|
|
|
|
|
|
|
); |
|
383
|
|
|
|
|
|
|
|
|
384
|
12
|
50
|
|
|
|
192
|
if( !$err ) { |
|
|
|
0
|
|
|
|
|
|
|
385
|
12
|
|
|
|
|
42
|
my $future = $self->loop->new_future->done( @results ); |
|
386
|
12
|
100
|
|
|
|
398
|
$future->on_done( $args{on_resolved} ) if $args{on_resolved}; |
|
387
|
12
|
|
|
|
|
103
|
return $future; |
|
388
|
|
|
|
|
|
|
} |
|
389
|
|
|
|
|
|
|
elsif( $err == EAI_NONAME ) { |
|
390
|
|
|
|
|
|
|
# fallthrough to async case |
|
391
|
|
|
|
|
|
|
} |
|
392
|
|
|
|
|
|
|
else { |
|
393
|
0
|
|
|
|
|
0
|
my $future = $self->loop->new_future->fail( $err, resolve => getaddrinfo => $err+0 ); |
|
394
|
0
|
0
|
|
|
|
0
|
$future->on_fail( $args{on_error} ) if $args{on_error}; |
|
395
|
0
|
|
|
|
|
0
|
return $future; |
|
396
|
|
|
|
|
|
|
} |
|
397
|
|
|
|
|
|
|
} |
|
398
|
|
|
|
|
|
|
|
|
399
|
|
|
|
|
|
|
my $future = $self->resolve( |
|
400
|
|
|
|
|
|
|
type => "getaddrinfo", |
|
401
|
|
|
|
|
|
|
data => [ |
|
402
|
|
|
|
|
|
|
host => $host, |
|
403
|
|
|
|
|
|
|
service => $service, |
|
404
|
|
|
|
|
|
|
flags => $flags, |
|
405
|
12
|
100
|
|
|
|
43
|
map { exists $args{$_} ? ( $_ => $args{$_} ) : () } qw( family socktype protocol ), |
|
406
|
|
|
|
|
|
|
], |
|
407
|
|
|
|
|
|
|
timeout => $args{timeout}, |
|
408
|
4
|
|
|
|
|
11
|
); |
|
409
|
|
|
|
|
|
|
|
|
410
|
4
|
100
|
|
|
|
27
|
$future->on_done( $args{on_resolved} ) if $args{on_resolved}; |
|
411
|
4
|
100
|
|
|
|
25
|
$future->on_fail( $args{on_error} ) if $args{on_error}; |
|
412
|
|
|
|
|
|
|
|
|
413
|
4
|
100
|
|
|
|
75
|
return $future if defined wantarray; |
|
414
|
|
|
|
|
|
|
|
|
415
|
|
|
|
|
|
|
# Caller is not going to keep hold of the Future, so we have to ensure it |
|
416
|
|
|
|
|
|
|
# stays alive somehow |
|
417
|
1
|
|
|
0
|
|
16
|
$self->adopt_future( $future->else( sub { Future->done } ) ); |
|
|
0
|
|
|
|
|
0
|
|
|
418
|
|
|
|
|
|
|
} |
|
419
|
|
|
|
|
|
|
|
|
420
|
|
|
|
|
|
|
=head2 getnameinfo |
|
421
|
|
|
|
|
|
|
|
|
422
|
|
|
|
|
|
|
( $host, $service ) = $resolver->getnameinfo( %args )->get |
|
423
|
|
|
|
|
|
|
|
|
424
|
|
|
|
|
|
|
A shortcut wrapper around the C resolver, taking its arguments in |
|
425
|
|
|
|
|
|
|
a more convenient form. |
|
426
|
|
|
|
|
|
|
|
|
427
|
|
|
|
|
|
|
=over 8 |
|
428
|
|
|
|
|
|
|
|
|
429
|
|
|
|
|
|
|
=item addr => STRING |
|
430
|
|
|
|
|
|
|
|
|
431
|
|
|
|
|
|
|
The packed socket address to look up. |
|
432
|
|
|
|
|
|
|
|
|
433
|
|
|
|
|
|
|
=item flags => INT |
|
434
|
|
|
|
|
|
|
|
|
435
|
|
|
|
|
|
|
Flags to control the C function. See the C constants in |
|
436
|
|
|
|
|
|
|
L's C for more detail. |
|
437
|
|
|
|
|
|
|
|
|
438
|
|
|
|
|
|
|
=item numerichost => BOOL |
|
439
|
|
|
|
|
|
|
|
|
440
|
|
|
|
|
|
|
=item numericserv => BOOL |
|
441
|
|
|
|
|
|
|
|
|
442
|
|
|
|
|
|
|
=item dgram => BOOL |
|
443
|
|
|
|
|
|
|
|
|
444
|
|
|
|
|
|
|
If true, set the C, C or C flags. |
|
445
|
|
|
|
|
|
|
|
|
446
|
|
|
|
|
|
|
=item numeric => BOOL |
|
447
|
|
|
|
|
|
|
|
|
448
|
|
|
|
|
|
|
If true, sets both C and C flags. |
|
449
|
|
|
|
|
|
|
|
|
450
|
|
|
|
|
|
|
=item timeout => NUMBER |
|
451
|
|
|
|
|
|
|
|
|
452
|
|
|
|
|
|
|
Time in seconds after which to abort the lookup with a C exception |
|
453
|
|
|
|
|
|
|
|
|
454
|
|
|
|
|
|
|
=back |
|
455
|
|
|
|
|
|
|
|
|
456
|
|
|
|
|
|
|
On failure, the detail field will give the error number, which should match |
|
457
|
|
|
|
|
|
|
one of the C constants. |
|
458
|
|
|
|
|
|
|
|
|
459
|
|
|
|
|
|
|
->fail( $message, resolve => getnameinfo => $eai_errno ) |
|
460
|
|
|
|
|
|
|
|
|
461
|
|
|
|
|
|
|
As a specific optimisation, this method will try to perform a lookup of |
|
462
|
|
|
|
|
|
|
numeric values synchronously, rather than asynchronously, if both the |
|
463
|
|
|
|
|
|
|
C and C flags are given. |
|
464
|
|
|
|
|
|
|
|
|
465
|
|
|
|
|
|
|
=head2 getnameinfo (void) |
|
466
|
|
|
|
|
|
|
|
|
467
|
|
|
|
|
|
|
$resolver->getnameinfo( %args ) |
|
468
|
|
|
|
|
|
|
|
|
469
|
|
|
|
|
|
|
When not returning a future, additional parameters can be given containing the |
|
470
|
|
|
|
|
|
|
continuations to invoke on success or failure: |
|
471
|
|
|
|
|
|
|
|
|
472
|
|
|
|
|
|
|
=over 8 |
|
473
|
|
|
|
|
|
|
|
|
474
|
|
|
|
|
|
|
=item on_resolved => CODE |
|
475
|
|
|
|
|
|
|
|
|
476
|
|
|
|
|
|
|
Callback which is invoked after a successful lookup. |
|
477
|
|
|
|
|
|
|
|
|
478
|
|
|
|
|
|
|
$on_resolved->( $host, $service ) |
|
479
|
|
|
|
|
|
|
|
|
480
|
|
|
|
|
|
|
=item on_error => CODE |
|
481
|
|
|
|
|
|
|
|
|
482
|
|
|
|
|
|
|
Callback which is invoked after a failed lookup, including for a timeout. |
|
483
|
|
|
|
|
|
|
|
|
484
|
|
|
|
|
|
|
$on_error->( $exception ) |
|
485
|
|
|
|
|
|
|
|
|
486
|
|
|
|
|
|
|
=back |
|
487
|
|
|
|
|
|
|
|
|
488
|
|
|
|
|
|
|
=cut |
|
489
|
|
|
|
|
|
|
|
|
490
|
|
|
|
|
|
|
sub getnameinfo |
|
491
|
|
|
|
|
|
|
{ |
|
492
|
5
|
|
|
5
|
1
|
4965
|
my $self = shift; |
|
493
|
5
|
|
|
|
|
26
|
my %args = @_; |
|
494
|
|
|
|
|
|
|
|
|
495
|
|
|
|
|
|
|
$args{on_resolved} or defined wantarray or |
|
496
|
5
|
50
|
66
|
|
|
32
|
croak "Expected 'on_resolved' or to return a Future"; |
|
497
|
|
|
|
|
|
|
|
|
498
|
|
|
|
|
|
|
$args{on_error} or defined wantarray or |
|
499
|
5
|
50
|
66
|
|
|
16
|
croak "Expected 'on_error' or to return a Future"; |
|
500
|
|
|
|
|
|
|
|
|
501
|
5
|
|
50
|
|
|
22
|
my $flags = $args{flags} || 0; |
|
502
|
|
|
|
|
|
|
|
|
503
|
5
|
50
|
|
|
|
12
|
$flags |= NI_NUMERICHOST if $args{numerichost}; |
|
504
|
5
|
50
|
|
|
|
8
|
$flags |= NI_NUMERICSERV if $args{numericserv}; |
|
505
|
5
|
50
|
|
|
|
10
|
$flags |= NI_DGRAM if $args{dgram}; |
|
506
|
|
|
|
|
|
|
|
|
507
|
5
|
100
|
|
|
|
11
|
$flags |= NI_NUMERICHOST|NI_NUMERICSERV if $args{numeric}; |
|
508
|
|
|
|
|
|
|
|
|
509
|
5
|
100
|
|
|
|
12
|
if( $flags & (NI_NUMERICHOST|NI_NUMERICSERV) ) { |
|
510
|
|
|
|
|
|
|
# This is a numeric-only lookup that can be done synchronously |
|
511
|
2
|
|
|
|
|
7
|
my ( $err, $host, $service ) = Socket::getnameinfo( $args{addr}, $flags ); |
|
512
|
|
|
|
|
|
|
|
|
513
|
2
|
50
|
|
|
|
38
|
if( $err ) { |
|
514
|
0
|
|
|
|
|
0
|
my $future = $self->loop->new_future->fail( $err, resolve => getnameinfo => $err+0 ); |
|
515
|
0
|
0
|
|
|
|
0
|
$future->on_fail( $args{on_error} ) if $args{on_error}; |
|
516
|
0
|
|
|
|
|
0
|
return $future; |
|
517
|
|
|
|
|
|
|
} |
|
518
|
|
|
|
|
|
|
else { |
|
519
|
2
|
|
|
|
|
6
|
my $future = $self->loop->new_future->done( $host, $service ); |
|
520
|
2
|
100
|
|
|
|
67
|
$future->on_done( $args{on_resolved} ) if $args{on_resolved}; |
|
521
|
2
|
|
|
|
|
23
|
return $future; |
|
522
|
|
|
|
|
|
|
} |
|
523
|
|
|
|
|
|
|
} |
|
524
|
|
|
|
|
|
|
|
|
525
|
|
|
|
|
|
|
my $future = $self->resolve( |
|
526
|
|
|
|
|
|
|
type => "getnameinfo", |
|
527
|
|
|
|
|
|
|
data => [ $args{addr}, $flags ], |
|
528
|
|
|
|
|
|
|
timeout => $args{timeout}, |
|
529
|
|
|
|
|
|
|
)->transform( |
|
530
|
3
|
|
|
3
|
|
255
|
done => sub { @{ $_[0] } }, # unpack the ARRAY ref |
|
|
3
|
|
|
|
|
9
|
|
|
531
|
3
|
|
|
|
|
13
|
); |
|
532
|
|
|
|
|
|
|
|
|
533
|
3
|
100
|
|
|
|
91
|
$future->on_done( $args{on_resolved} ) if $args{on_resolved}; |
|
534
|
3
|
100
|
|
|
|
24
|
$future->on_fail( $args{on_error} ) if $args{on_error}; |
|
535
|
|
|
|
|
|
|
|
|
536
|
3
|
100
|
|
|
|
25
|
return $future if defined wantarray; |
|
537
|
|
|
|
|
|
|
|
|
538
|
|
|
|
|
|
|
# Caller is not going to keep hold of the Future, so we have to ensure it |
|
539
|
|
|
|
|
|
|
# stays alive somehow |
|
540
|
1
|
|
|
0
|
|
16
|
$self->adopt_future( $future->else( sub { Future->done } ) ); |
|
|
0
|
|
|
|
|
0
|
|
|
541
|
|
|
|
|
|
|
} |
|
542
|
|
|
|
|
|
|
|
|
543
|
|
|
|
|
|
|
=head1 FUNCTIONS |
|
544
|
|
|
|
|
|
|
|
|
545
|
|
|
|
|
|
|
=cut |
|
546
|
|
|
|
|
|
|
|
|
547
|
|
|
|
|
|
|
=head2 register_resolver( $name, $code ) |
|
548
|
|
|
|
|
|
|
|
|
549
|
|
|
|
|
|
|
Registers a new named resolver function that can be called by the C |
|
550
|
|
|
|
|
|
|
method. All named resolvers must be registered before the object is |
|
551
|
|
|
|
|
|
|
constructed. |
|
552
|
|
|
|
|
|
|
|
|
553
|
|
|
|
|
|
|
=over 8 |
|
554
|
|
|
|
|
|
|
|
|
555
|
|
|
|
|
|
|
=item $name |
|
556
|
|
|
|
|
|
|
|
|
557
|
|
|
|
|
|
|
The name of the resolver function; must be a plain string. This name will be |
|
558
|
|
|
|
|
|
|
used by the C argument to the C method, to identify it. |
|
559
|
|
|
|
|
|
|
|
|
560
|
|
|
|
|
|
|
=item $code |
|
561
|
|
|
|
|
|
|
|
|
562
|
|
|
|
|
|
|
A CODE reference to the resolver function body. It will be called in list |
|
563
|
|
|
|
|
|
|
context, being passed the list of arguments given in the C argument to |
|
564
|
|
|
|
|
|
|
the C method. The returned list will be passed to the |
|
565
|
|
|
|
|
|
|
C callback. If the code throws an exception at call time, it will |
|
566
|
|
|
|
|
|
|
be passed to the C continuation. If it returns normally, the list of |
|
567
|
|
|
|
|
|
|
values it returns will be passed to C. |
|
568
|
|
|
|
|
|
|
|
|
569
|
|
|
|
|
|
|
=back |
|
570
|
|
|
|
|
|
|
|
|
571
|
|
|
|
|
|
|
=cut |
|
572
|
|
|
|
|
|
|
|
|
573
|
|
|
|
|
|
|
# Plain function, not a method |
|
574
|
|
|
|
|
|
|
sub register_resolver |
|
575
|
|
|
|
|
|
|
{ |
|
576
|
105
|
|
|
105
|
1
|
143
|
my ( $name, $code ) = @_; |
|
577
|
|
|
|
|
|
|
|
|
578
|
105
|
50
|
|
|
|
159
|
croak "Cannot register new resolver methods once the resolver has been started" if $started; |
|
579
|
|
|
|
|
|
|
|
|
580
|
105
|
50
|
|
|
|
162
|
croak "Already have a resolver method called '$name'" if exists $METHODS{$name}; |
|
581
|
105
|
|
|
|
|
161
|
$METHODS{$name} = $code; |
|
582
|
|
|
|
|
|
|
} |
|
583
|
|
|
|
|
|
|
|
|
584
|
|
|
|
|
|
|
=head1 BUILT-IN RESOLVERS |
|
585
|
|
|
|
|
|
|
|
|
586
|
|
|
|
|
|
|
The following resolver names are implemented by the same-named perl function, |
|
587
|
|
|
|
|
|
|
taking and returning a list of values exactly as the perl function does: |
|
588
|
|
|
|
|
|
|
|
|
589
|
|
|
|
|
|
|
getpwnam getpwuid |
|
590
|
|
|
|
|
|
|
getgrnam getgrgid |
|
591
|
|
|
|
|
|
|
getservbyname getservbyport |
|
592
|
|
|
|
|
|
|
gethostbyname gethostbyaddr |
|
593
|
|
|
|
|
|
|
getnetbyname getnetbyaddr |
|
594
|
|
|
|
|
|
|
getprotobyname getprotobynumber |
|
595
|
|
|
|
|
|
|
|
|
596
|
|
|
|
|
|
|
=cut |
|
597
|
|
|
|
|
|
|
|
|
598
|
|
|
|
|
|
|
# Now register the inbuilt methods |
|
599
|
|
|
|
|
|
|
|
|
600
|
|
|
|
|
|
|
register_resolver getpwnam => sub { my @r = getpwnam( $_[0] ) or die "$!\n"; @r }; |
|
601
|
|
|
|
|
|
|
register_resolver getpwuid => sub { my @r = getpwuid( $_[0] ) or die "$!\n"; @r }; |
|
602
|
|
|
|
|
|
|
|
|
603
|
|
|
|
|
|
|
register_resolver getgrnam => sub { my @r = getgrnam( $_[0] ) or die "$!\n"; @r }; |
|
604
|
|
|
|
|
|
|
register_resolver getgrgid => sub { my @r = getgrgid( $_[0] ) or die "$!\n"; @r }; |
|
605
|
|
|
|
|
|
|
|
|
606
|
|
|
|
|
|
|
register_resolver getservbyname => sub { my @r = getservbyname( $_[0], $_[1] ) or die "$!\n"; @r }; |
|
607
|
|
|
|
|
|
|
register_resolver getservbyport => sub { my @r = getservbyport( $_[0], $_[1] ) or die "$!\n"; @r }; |
|
608
|
|
|
|
|
|
|
|
|
609
|
|
|
|
|
|
|
register_resolver gethostbyname => sub { my @r = gethostbyname( $_[0] ) or die "$!\n"; @r }; |
|
610
|
|
|
|
|
|
|
register_resolver gethostbyaddr => sub { my @r = gethostbyaddr( $_[0], $_[1] ) or die "$!\n"; @r }; |
|
611
|
|
|
|
|
|
|
|
|
612
|
|
|
|
|
|
|
register_resolver getnetbyname => sub { my @r = getnetbyname( $_[0] ) or die "$!\n"; @r }; |
|
613
|
|
|
|
|
|
|
register_resolver getnetbyaddr => sub { my @r = getnetbyaddr( $_[0], $_[1] ) or die "$!\n"; @r }; |
|
614
|
|
|
|
|
|
|
|
|
615
|
|
|
|
|
|
|
register_resolver getprotobyname => sub { my @r = getprotobyname( $_[0] ) or die "$!\n"; @r }; |
|
616
|
|
|
|
|
|
|
register_resolver getprotobynumber => sub { my @r = getprotobynumber( $_[0] ) or die "$!\n"; @r }; |
|
617
|
|
|
|
|
|
|
|
|
618
|
|
|
|
|
|
|
=pod |
|
619
|
|
|
|
|
|
|
|
|
620
|
|
|
|
|
|
|
The following three resolver names are implemented using the L module. |
|
621
|
|
|
|
|
|
|
|
|
622
|
|
|
|
|
|
|
getaddrinfo |
|
623
|
|
|
|
|
|
|
getaddrinfo_array |
|
624
|
|
|
|
|
|
|
getnameinfo |
|
625
|
|
|
|
|
|
|
|
|
626
|
|
|
|
|
|
|
The C resolver takes arguments in a hash of name/value pairs and |
|
627
|
|
|
|
|
|
|
returns a list of hash structures, as the C function |
|
628
|
|
|
|
|
|
|
does. For neatness it takes all its arguments as named values; taking the host |
|
629
|
|
|
|
|
|
|
and service names from arguments called C and C respectively; |
|
630
|
|
|
|
|
|
|
all the remaining arguments are passed into the hints hash. This name is also |
|
631
|
|
|
|
|
|
|
aliased as simply C. |
|
632
|
|
|
|
|
|
|
|
|
633
|
|
|
|
|
|
|
The C resolver behaves more like the C version of |
|
634
|
|
|
|
|
|
|
the function. It takes hints in a flat list, and mangles the result of the |
|
635
|
|
|
|
|
|
|
function, so that the returned value is more useful to the caller. It splits |
|
636
|
|
|
|
|
|
|
up the list of 5-tuples into a list of ARRAY refs, where each referenced array |
|
637
|
|
|
|
|
|
|
contains one of the tuples of 5 values. |
|
638
|
|
|
|
|
|
|
|
|
639
|
|
|
|
|
|
|
As an extra convenience to the caller, both resolvers will also accept plain |
|
640
|
|
|
|
|
|
|
string names for the C argument, converting C and possibly |
|
641
|
|
|
|
|
|
|
C into the appropriate C value, and for the C argument, |
|
642
|
|
|
|
|
|
|
converting C, C or C into the appropriate C value. |
|
643
|
|
|
|
|
|
|
|
|
644
|
|
|
|
|
|
|
The C resolver returns its result in the same form as C. |
|
645
|
|
|
|
|
|
|
|
|
646
|
|
|
|
|
|
|
Because this module simply uses the system's C resolver, it will |
|
647
|
|
|
|
|
|
|
be fully IPv6-aware if the underlying platform's resolver is. This allows |
|
648
|
|
|
|
|
|
|
programs to be fully IPv6-capable. |
|
649
|
|
|
|
|
|
|
|
|
650
|
|
|
|
|
|
|
=cut |
|
651
|
|
|
|
|
|
|
|
|
652
|
|
|
|
|
|
|
register_resolver getaddrinfo => sub { |
|
653
|
|
|
|
|
|
|
my %args = @_; |
|
654
|
|
|
|
|
|
|
|
|
655
|
|
|
|
|
|
|
my $host = delete $args{host}; |
|
656
|
|
|
|
|
|
|
my $service = delete $args{service}; |
|
657
|
|
|
|
|
|
|
|
|
658
|
|
|
|
|
|
|
$args{family} = IO::Async::OS->getfamilybyname( $args{family} ) if defined $args{family}; |
|
659
|
|
|
|
|
|
|
$args{socktype} = IO::Async::OS->getsocktypebyname( $args{socktype} ) if defined $args{socktype}; |
|
660
|
|
|
|
|
|
|
|
|
661
|
|
|
|
|
|
|
# Clear any other existing but undefined hints |
|
662
|
|
|
|
|
|
|
defined $args{$_} or delete $args{$_} for keys %args; |
|
663
|
|
|
|
|
|
|
|
|
664
|
|
|
|
|
|
|
my ( $err, @addrs ) = Socket::getaddrinfo( $host, $service, \%args ); |
|
665
|
|
|
|
|
|
|
|
|
666
|
|
|
|
|
|
|
die [ "$err", $err+0 ] if $err; |
|
667
|
|
|
|
|
|
|
|
|
668
|
|
|
|
|
|
|
return @addrs; |
|
669
|
|
|
|
|
|
|
}; |
|
670
|
|
|
|
|
|
|
|
|
671
|
|
|
|
|
|
|
register_resolver getaddrinfo_array => sub { |
|
672
|
|
|
|
|
|
|
my ( $host, $service, $family, $socktype, $protocol, $flags ) = @_; |
|
673
|
|
|
|
|
|
|
|
|
674
|
|
|
|
|
|
|
$family = IO::Async::OS->getfamilybyname( $family ); |
|
675
|
|
|
|
|
|
|
$socktype = IO::Async::OS->getsocktypebyname( $socktype ); |
|
676
|
|
|
|
|
|
|
|
|
677
|
|
|
|
|
|
|
my %hints; |
|
678
|
|
|
|
|
|
|
$hints{family} = $family if defined $family; |
|
679
|
|
|
|
|
|
|
$hints{socktype} = $socktype if defined $socktype; |
|
680
|
|
|
|
|
|
|
$hints{protocol} = $protocol if defined $protocol; |
|
681
|
|
|
|
|
|
|
$hints{flags} = $flags if defined $flags; |
|
682
|
|
|
|
|
|
|
|
|
683
|
|
|
|
|
|
|
my ( $err, @addrs ) = Socket::getaddrinfo( $host, $service, \%hints ); |
|
684
|
|
|
|
|
|
|
|
|
685
|
|
|
|
|
|
|
die [ "$err", $err+0 ] if $err; |
|
686
|
|
|
|
|
|
|
|
|
687
|
|
|
|
|
|
|
# Convert the @addrs list into a list of ARRAY refs of 5 values each |
|
688
|
|
|
|
|
|
|
return map { |
|
689
|
|
|
|
|
|
|
[ $_->{family}, $_->{socktype}, $_->{protocol}, $_->{addr}, $_->{canonname} ] |
|
690
|
|
|
|
|
|
|
} @addrs; |
|
691
|
|
|
|
|
|
|
}; |
|
692
|
|
|
|
|
|
|
|
|
693
|
|
|
|
|
|
|
register_resolver getnameinfo => sub { |
|
694
|
|
|
|
|
|
|
my ( $addr, $flags ) = @_; |
|
695
|
|
|
|
|
|
|
|
|
696
|
|
|
|
|
|
|
my ( $err, $host, $service ) = Socket::getnameinfo( $addr, $flags || 0 ); |
|
697
|
|
|
|
|
|
|
|
|
698
|
|
|
|
|
|
|
die [ "$err", $err+0 ] if $err; |
|
699
|
|
|
|
|
|
|
|
|
700
|
|
|
|
|
|
|
return [ $host, $service ]; |
|
701
|
|
|
|
|
|
|
}; |
|
702
|
|
|
|
|
|
|
|
|
703
|
|
|
|
|
|
|
=head1 EXAMPLES |
|
704
|
|
|
|
|
|
|
|
|
705
|
|
|
|
|
|
|
The following somewhat contrieved example shows how to implement a new |
|
706
|
|
|
|
|
|
|
resolver function. This example just uses in-memory data, but a real function |
|
707
|
|
|
|
|
|
|
would likely make calls to OS functions to provide an answer. In traditional |
|
708
|
|
|
|
|
|
|
Unix style, a pair of functions are provided that each look up the entity by |
|
709
|
|
|
|
|
|
|
either type of key, where both functions return the same type of list. This is |
|
710
|
|
|
|
|
|
|
purely a convention, and is in no way required or enforced by the |
|
711
|
|
|
|
|
|
|
L itself. |
|
712
|
|
|
|
|
|
|
|
|
713
|
|
|
|
|
|
|
@numbers = qw( zero one two three four |
|
714
|
|
|
|
|
|
|
five six seven eight nine ); |
|
715
|
|
|
|
|
|
|
|
|
716
|
|
|
|
|
|
|
register_resolver getnumberbyindex => sub { |
|
717
|
|
|
|
|
|
|
my ( $index ) = @_; |
|
718
|
|
|
|
|
|
|
die "Bad index $index" unless $index >= 0 and $index < @numbers; |
|
719
|
|
|
|
|
|
|
return ( $index, $numbers[$index] ); |
|
720
|
|
|
|
|
|
|
}; |
|
721
|
|
|
|
|
|
|
|
|
722
|
|
|
|
|
|
|
register_resolver getnumberbyname => sub { |
|
723
|
|
|
|
|
|
|
my ( $name ) = @_; |
|
724
|
|
|
|
|
|
|
foreach my $index ( 0 .. $#numbers ) { |
|
725
|
|
|
|
|
|
|
return ( $index, $name ) if $numbers[$index] eq $name; |
|
726
|
|
|
|
|
|
|
} |
|
727
|
|
|
|
|
|
|
die "Bad name $name"; |
|
728
|
|
|
|
|
|
|
}; |
|
729
|
|
|
|
|
|
|
|
|
730
|
|
|
|
|
|
|
=head1 AUTHOR |
|
731
|
|
|
|
|
|
|
|
|
732
|
|
|
|
|
|
|
Paul Evans |
|
733
|
|
|
|
|
|
|
|
|
734
|
|
|
|
|
|
|
=cut |
|
735
|
|
|
|
|
|
|
|
|
736
|
|
|
|
|
|
|
0x55AA; |