Skip to content

Instantly share code, notes, and snippets.

@fskale
Last active June 24, 2023 16:43
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fskale/c877fa9606a5669dc908d13f2038f678 to your computer and use it in GitHub Desktop.
Save fskale/c877fa9606a5669dc908d13f2038f678 to your computer and use it in GitHub Desktop.
Async (using Mojolicious, and Future::AsyncAwait) DNS resolution demonstration !
#!/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