Skip to content

Commit

Permalink
Fix deserialization logic for mode, stratum, poll and precision
Browse files Browse the repository at this point in the history
  • Loading branch information
stoyicker committed Nov 7, 2023
1 parent 2b7b15d commit c88dff1
Showing 1 changed file with 41 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,21 @@ import kotlin.time.Duration.Companion.seconds

internal class NtpPacketDeserializer {
operator fun invoke(bytes: ByteArray): NtpPacket? {
val bits = bytes.flatMap { it.toString(2).asIterable() }
val bits = bytes.map { it.toInt() }
.flatMap {
listOf(
it and 1,
it and (1 shl 1),
it and (1 shl 2),
it and (1 shl 3),
it and (1 shl 4),
it and (1 shl 5),
it and (1 shl 6),
it and (1 shl 7),
).map {
it != 0
}
}
var startIndexInclusive = 0
var endIndexExclusive = 2
var index = 0
Expand All @@ -18,6 +32,21 @@ internal class NtpPacketDeserializer {
startIndexInclusive = endIndexExclusive
endIndexExclusive += 3
val versionNumber = bits.bitRangeAsInt(startIndexInclusive until endIndexExclusive)
startIndexInclusive = endIndexExclusive
endIndexExclusive += 3
val mode = bits.bitRangeAsInt(startIndexInclusive until endIndexExclusive)
startIndexInclusive = endIndexExclusive
endIndexExclusive += 8
val stratum = bytes[1].asInt
if (stratum >= STRATUM_CLOCK_NOT_SYNCHRONIZED) {
return null
}
startIndexInclusive = endIndexExclusive
endIndexExclusive += 8
val poll = bytes[2].asInt
startIndexInclusive = endIndexExclusive
endIndexExclusive += 8
val precision = bytes[3].asInt
return NtpPacket(
(bytes[index++].toInt() shl 8) + bytes[index++],
(bytes[index++].toInt() shl 16) + (bytes[index++].toInt() shl 24) + bytes[index++],
Expand All @@ -41,8 +70,16 @@ internal class NtpPacketDeserializer {
)
}

private fun List<Char>.bitRangeAsInt(intRange: IntRange) =
subList(intRange.first, intRange.last + 1).joinToString(separator = "").toInt(2)
private fun List<Boolean>.bitRangeAsInt(intRange: IntRange) =
subList(intRange.first, intRange.last + 1).foldIndexed(0) { i, acc, it ->
when (it) {
true -> 2F.pow(i).toInt()
false -> 0
} + acc
}

private val Byte.asInt
get() = toUByte().toInt()

private val ByteArray.asNtpIntervalToInterval: Duration
get() {
Expand Down Expand Up @@ -86,5 +123,6 @@ internal class NtpPacketDeserializer {

companion object {
private const val LEAP_INDICATOR_CLOCK_UNSYNCHRONIZED = 0b11
private const val STRATUM_CLOCK_NOT_SYNCHRONIZED = 16
}
}

0 comments on commit c88dff1

Please sign in to comment.