diff --git a/akka-actor/src/main/scala/akka/io/dns/CachePolicy.scala b/akka-actor/src/main/scala/akka/io/dns/CachePolicy.scala index 0920df81b0..b8feebde0f 100644 --- a/akka-actor/src/main/scala/akka/io/dns/CachePolicy.scala +++ b/akka-actor/src/main/scala/akka/io/dns/CachePolicy.scala @@ -15,7 +15,8 @@ object CachePolicy { case object Forever extends CachePolicy final class Ttl private (val value: FiniteDuration) extends CachePolicy { - if (value <= Duration.Zero) throw new IllegalArgumentException(s"TTL values must be a positive value.") + if (value < Duration.Zero) + throw new IllegalArgumentException(s"TTL values must be a positive value (zero included).") import akka.util.JavaDurationConverters._ def getValue: java.time.Duration = value.asJava @@ -32,10 +33,16 @@ object CachePolicy { object Ttl { def unapply(ttl: Ttl): Option[FiniteDuration] = Some(ttl.value) def fromPositive(value: FiniteDuration): Ttl = { + if (value <= Duration.Zero) + throw new IllegalArgumentException( + s"Positive TTL values must be a strictly positive value. Use Ttl.never for zero.") new Ttl(value) } def fromPositive(value: java.time.Duration): Ttl = fromPositive(value.asScala) + // DNS RFC states that zero values are interpreted to mean that the RR should not be cached + val never: Ttl = new Ttl(0.seconds) + // There's places where only a Ttl makes sense (DNS RFC says TTL is a positive 32 bit integer) // but we know the value can be cached effectively forever (e.g. the Lookup name was the actual IP already) val effectivelyForever: Ttl = fromPositive(Int.MaxValue.seconds) diff --git a/akka-actor/src/main/scala/akka/io/dns/DnsResourceRecords.scala b/akka-actor/src/main/scala/akka/io/dns/DnsResourceRecords.scala index 28f05d7fd1..843bde2029 100644 --- a/akka-actor/src/main/scala/akka/io/dns/DnsResourceRecords.scala +++ b/akka-actor/src/main/scala/akka/io/dns/DnsResourceRecords.scala @@ -138,7 +138,10 @@ private[dns] object ResourceRecord { val recType = it.getShort val recClass = it.getShort // According to https://www.ietf.org/rfc/rfc1035.txt: "TTL: positive values of a signed 32 bit number." - val ttl = Ttl.fromPositive(it.getInt.seconds) + val ttl = (it.getInt: @switch) match { + case 0 => Ttl.never + case nonZero => Ttl.fromPositive(nonZero.seconds) + } val rdLength = it.getShort val data = it.clone().take(rdLength) it.drop(rdLength)