Last active
June 24, 2023 16:43
-
-
Save fskale/c877fa9606a5669dc908d13f2038f678 to your computer and use it in GitHub Desktop.
Async (using Mojolicious, and Future::AsyncAwait) DNS resolution demonstration !
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env perl | |
use 5.026; | |
use Mojo::Base -strict, -signatures, -async_await; | |
use Mojo::Promise; | |
use Socket qw(:addrinfo IPPROTO_UDP SOCK_DGRAM AF_INET AF_INET6); | |
use Mojo::Collection 'c'; | |
use Net::DNS::Native; | |
sub _resolve_host ($host, $resolve, $reject) { | |
my $dns = Net::DNS::Native->new(pool => 5, extra_thread => 1); | |
my $fh = $dns->getaddrinfo($host, 161, {protocol => IPPROTO_UDP, socktype => SOCK_DGRAM, family => AF_INET}); | |
Mojo::IOLoop->singleton->reactor->io( | |
$fh => sub { | |
my $reactor = shift; | |
$reactor->remove($fh); | |
my ($err, @res) = $dns->get_result($fh); | |
if ($err and !@res) { | |
printf(STDERR "_resolve_host: %s - Error: %s\n", $host, $err); | |
$reject->($err); | |
} | |
else { | |
foreach my $entry (@res) { | |
my ($err, $ip, $servicename) = getnameinfo($entry->{addr}, NI_NUMERICHOST); | |
if ($ip) { | |
$resolve->($ip); | |
} | |
elsif ($err) { | |
printf(STDERR "\n_resolve_host: %s - Name resolution error: %s\n", $host, $err); | |
$reject->($err); | |
} | |
} | |
} | |
} | |
)->watch($fh, 1, 0); | |
} | |
my $ips = c(); | |
async sub resolve ($host) { | |
# Wrap a continuation-passing style API | |
Mojo::Promise->new( | |
sub ($resolve, $reject) { | |
_resolve_host($host, $resolve, $reject); | |
} | |
)->then(sub ($result) { | |
push(@{$ips}, sprintf("%s => %s", $host, $result)); | |
})->catch(sub ($err) { | |
warn($err); | |
})->wait; | |
} | |
sub do_resolve (@hosts) { | |
my @promises = (); | |
push(@promises, resolve($_)) for @hosts; | |
Mojo::Promise->all(@promises)->catch(sub ($err) { | |
printf(STDERR "Error: %s", $err); | |
})->finally(sub { | |
printf("DNS Resolution done for hosts %s\n", $_) for @hosts; | |
})->wait; | |
} | |
do_resolve(qw/google.at kernel.org/); | |
do_resolve(qw/amazon.com microsoft.com/); | |
do_resolve(qw/aws.com azure.com/); | |
printf("\nIPs:\n%s\n", $ips->join("\n")); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment