diff --git a/lib/async/scheduler.rb b/lib/async/scheduler.rb index 68cc8bd1..b213e83d 100644 --- a/lib/async/scheduler.rb +++ b/lib/async/scheduler.rb @@ -295,7 +295,26 @@ def address_resolve(hostname) # On some platforms, hostnames may contain a device-specific suffix (e.g. %en0). We need to strip this before resolving. # See for more details. hostname = hostname.split("%", 2).first - ::Resolv.getaddresses(hostname) + + return [hostname] if ::Resolv::AddressRegex =~ hostname + + ::Resolv::DefaultResolver.instance_variable_get(:@resolvers).each do |resolver| + addresses = [] + + if resolver.is_a?(::Resolv::DNS) + [::Resolv::DNS::Resource::IN::AAAA, ::Resolv::DNS::Resource::IN::A].each do |type| + resolver.each_resource(hostname, type) {|resource| addresses << resource.address.to_s} + end + else + resolver.each_address(hostname) {|address| addresses << address.to_s} + ipv6, ipv4 = addresses.partition {|address| address.include?(":")} + addresses = ipv6 + ipv4 + end + + return addresses unless addresses.empty? + end + + return [] end # Wait for the specified IO to become ready for the specified events. diff --git a/test/async/scheduler/address.rb b/test/async/scheduler/address.rb index db80b617..d6f4458f 100644 --- a/test/async/scheduler/address.rb +++ b/test/async/scheduler/address.rb @@ -34,4 +34,17 @@ expect(address.ipv6?).to be == true end end + + with "#address_resolve" do + it "orders IPv6 addresses before IPv4 addresses" do + addresses = Fiber.scheduler.address_resolve("localhost") + + ipv4_index = addresses.index {|address| !address.include?(":")} + ipv6_index = addresses.index {|address| address.include?(":")} + + if ipv4_index && ipv6_index + expect(ipv6_index).to be < ipv4_index + end + end + end end