=dns #25451 resolve raw IP addresses in async-dns

This commit is contained in:
Konrad Malawski 2018-08-09 12:27:57 +09:00 committed by Konrad `ktoso` Malawski
parent 36224f924b
commit fd59579790
2 changed files with 39 additions and 5 deletions

View file

@ -90,7 +90,9 @@ class AsyncDnsResolverIntegrationSpec extends AkkaSpec(
implicit val timeout = Timeout(duration)
"Resolver" must {
pending
pending // PENDING since needs `bind` server to be running to test end-to-end
"resolve single A record" in {
val name = "a-single.akka.test"
val answer = resolve(name, DnsProtocol.Ip(ipv6 = false))
@ -181,6 +183,23 @@ class AsyncDnsResolverIntegrationSpec extends AkkaSpec(
)
}
"not hang when resolving raw IP address" in {
val name = "127.0.0.1"
val answer = resolve(name)
answer.name shouldEqual name
answer.results.collect { case r: ARecord r }.toSet shouldEqual Set(
ARecord("127.0.0.1", Int.MaxValue, InetAddress.getByName("127.0.0.1"))
)
}
"not hang when resolving raw IPv6 address" in {
val name = "1:2:3:0:0:0:0:0"
val answer = resolve(name)
answer.name shouldEqual name
answer.results.collect { case r: ARecord r }.toSet shouldEqual Set(
ARecord("1:2:3:0:0:0:0:0", Int.MaxValue, InetAddress.getByName("1:2:3:0:0:0:0:0"))
)
}
"resolve same address twice" in {
resolve("a-single.akka.test").results.map(_.asInstanceOf[ARecord].ip) shouldEqual Seq(InetAddress.getByName("192.168.1.20"))
resolve("a-single.akka.test").results.map(_.asInstanceOf[ARecord].ip) shouldEqual Seq(InetAddress.getByName("192.168.1.20"))

View file

@ -4,13 +4,14 @@
package akka.io.dns.internal
import java.net.InetSocketAddress
import java.net.{ InetAddress, InetSocketAddress }
import java.nio.charset.StandardCharsets
import akka.actor.{ Actor, ActorLogging, ActorRef, ActorRefFactory, Props }
import akka.annotation.InternalApi
import akka.io.dns.DnsProtocol.{ Ip, RequestType, Srv }
import akka.io.dns.internal.DnsClient._
import akka.io.dns.{ DnsProtocol, DnsSettings, ResourceRecord }
import akka.io.dns.{ ARecord, DnsProtocol, DnsSettings, ResourceRecord }
import akka.pattern.{ ask, pipe }
import akka.util.{ Helpers, Timeout }
@ -49,7 +50,8 @@ private[io] final class AsyncDnsResolver(
override def receive: Receive = {
case DnsProtocol.Resolve(name, _) if isInetAddress(name)
log.warning("Tried to resolve ip [{}]. Ignoring.", name)
log.warning("Tried to resolve ip [{}], assuming resolved.", name)
alreadyResolvedIp(name) pipeTo sender()
case DnsProtocol.Resolve(name, mode)
resolve(name, mode, resolvers) pipeTo sender()
}
@ -66,6 +68,18 @@ private[io] final class AsyncDnsResolver(
}
}
private def alreadyResolvedIp(knownToBeIp: String): Future[DnsProtocol.Resolved] = {
if (isInetAddress(knownToBeIp))
Future {
val address = InetAddress.getByName(knownToBeIp) // only checks validity, since known to be IP address
val record = ARecord(knownToBeIp, Int.MaxValue, address)
DnsProtocol.Resolved(knownToBeIp, record :: Nil)
}
else
Future.failed(new IllegalArgumentException("Attempted to emit Resolved for known-to-be IP address, " +
s"yet argument was not an IP address, was: ${knownToBeIp}"))
}
private def sendQuestion(resolver: ActorRef, message: DnsQuestion): Future[Seq[ResourceRecord]] = {
val result = (resolver ? message).mapTo[Answer].map(_.rrs)
result.onFailure {
@ -142,7 +156,8 @@ private[io] object AsyncDnsResolver {
"""^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$""".r
private def isInetAddress(name: String): Boolean =
ipv4Address.findAllMatchIn(name).nonEmpty || ipv6Address.findAllMatchIn(name).nonEmpty
ipv4Address.findAllMatchIn(name).nonEmpty ||
ipv6Address.findAllMatchIn(name).nonEmpty
private val Empty = Future.successful(immutable.Seq.empty[ResourceRecord])