diff --git a/akka-actor/src/main/scala/akka/io/Dns.scala b/akka-actor/src/main/scala/akka/io/Dns.scala index fb621334e4..1c7d0c67f7 100644 --- a/akka-actor/src/main/scala/akka/io/Dns.scala +++ b/akka-actor/src/main/scala/akka/io/Dns.scala @@ -26,7 +26,7 @@ object Dns extends ExtensionId[DnsExt] with ExtensionIdProvider { } case class Resolved(name: String, ipv4: immutable.Seq[Inet4Address], ipv6: immutable.Seq[Inet6Address]) extends Command { - val addrOption: Option[InetAddress] = ipv4.headOption orElse ipv6.headOption + val addrOption: Option[InetAddress] = IpVersionSelector.getInetAddress(ipv4.headOption, ipv6.headOption) @throws[UnknownHostException] def addr: InetAddress = addrOption match { @@ -89,3 +89,11 @@ class DnsExt(system: ExtendedActorSystem) extends IO.Extension { def getResolver: ActorRef = manager } + +object IpVersionSelector { + def getInetAddress(ipv4: Option[Inet4Address], ipv6: Option[Inet6Address]): Option[InetAddress] = + System.getProperty("java.net.preferIPv6Addresses") match { + case "true" ⇒ ipv6 orElse ipv4 + case _ ⇒ ipv4 orElse ipv6 + } +} \ No newline at end of file diff --git a/akka-remote-tests/src/multi-jvm/scala/akka/io/DnsSpec.scala b/akka-remote-tests/src/multi-jvm/scala/akka/io/DnsSpec.scala new file mode 100644 index 0000000000..2ca5b64d14 --- /dev/null +++ b/akka-remote-tests/src/multi-jvm/scala/akka/io/DnsSpec.scala @@ -0,0 +1,56 @@ +/** + * Copyright (C) 2017 Lightbend Inc. + */ +package akka.io + +import java.net.Inet4Address +import java.net.Inet6Address +import java.net.InetAddress +import akka.remote.RemotingMultiNodeSpec +import akka.remote.testkit.MultiNodeConfig + +object DnsSpec extends MultiNodeConfig { + val first = role("first") +} + +class DnsSpecMultiJvmNode1 extends DnsSpec + +// This is a multi-jvm tests because it is modifying global System.properties +class DnsSpec extends RemotingMultiNodeSpec(DnsSpec) { + + def initialParticipants = roles.size + + val ip4Address = InetAddress.getByAddress("localhost", Array[Byte](127, 0, 0, 1)) match { + case address: Inet4Address ⇒ address + } + val ipv6Address = InetAddress.getByAddress("localhost", Array[Byte](0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1)) match { + case address: Inet6Address ⇒ address + } + + var temporaryValue: Option[String] = None + + override def atStartup(): Unit = { + temporaryValue = sys.props.get("java.net.preferIPv6Addresses") + } + + override def afterTermination(): Unit = { + temporaryValue match { + case Some(value) ⇒ sys.props.put("java.net.preferIPv6Addresses", value) + case _ ⇒ sys.props.remove("java.net.preferIPv6Addresses") + } + } + + "Dns" must { + + "resolve to a IPv6 address if it is the preferred network stack" in { + sys.props.put("java.net.preferIPv6Addresses", true.toString) + Dns.Resolved("test", List(ip4Address), List(ipv6Address)).addr should ===(ipv6Address) + } + "resolve to a IPv4 address if IPv6 is not the preferred network stack" in { + sys.props.remove("java.net.preferIPv6Addresses") + Dns.Resolved("test", List(ip4Address), List(ipv6Address)).addr should ===(ip4Address) + } + + } + +}