Kotlin version of the excellent https://implement-dns.wizardzines.com
- Using Kotlin
data
classes for theDNSHeader
andDNSQuestion
- The member variable names were changed to CamelCase rather than have underbars separating words
- The
DNSHeader.flags
variable in Kotlin is aBitSet
rather than an Int, because that field is 16 bit with an odd format and BitSet is easy to work with in Kotlin - The
DNSQuestion.name
variable is a String rather than array of bytes, as Strings are easy to work with and convert to bytes in Kotlin
- Rather than the standalone functions
header_to_bytes
andquestion_to_bytes
, the data classes each have atoByteArray()
function that knows how to write out the object to the needed binary format. - Since Kotlin doesn't have the equivalent of a
struct.pack()
, thetoByteArray()
in each class uses aDataOutputStream
to write itself into an array of bytes. It's similar in that the class's variables areInt
types, which are 32 bits in Kotlin, but are written to the byte array as 16 bit/2 byte Shorts. - Each
DataOutputStream
writes each field in the class to a backingByteArrayOutputStream
. - The
DataOutputStream
uses the.use {}
Kotlin lambda, which will do a try-with-resources on the output stream. - All byte arrays in the JVM are "big endian" by default, so we don't need to specify anything for that.
- The
DNSQuestion
name is encoded using a Kotlin function chain. First thename
is chopped up in into a list using thesplit
function on the.
character. Then each element from thesplit
uses themap
function to transform from aString
to aByteArray
. Then aforEach
function is used for each nowByteArray
element to write the length of the element and then the value of the element to theDataOutputStream
. - After the name is processed, then a
0
is written as a delimiter, and then the type and class fields. Again, these areInt
fields on the classes getting written asShort
types to the output stream, which is similar to the "H" in thestring.pack("!HH", 3, 34)
approach.
- Since the
DNSQuestion.name
encoding is part of thetoByteArray()
function, it's not called from thebuildQuery()
function. - The constructors of the classes provide sensible defaults, like
DNSHeader.name
but they are overriden in thebuildQuery()
function for example's sake. - The
BitSet
class used for theDNSHeader.flags
variable is from Java, so to make it more usable in Kotlin, thebitset
typesafe builder is used to initialize aBitSet
and set the 8th bit to true. - The
+
operator is used to concatenate the byte array representations of theDNSHeader
andDNSQuestion
instances.
- In order to see the query as a hex string, a Kotlin helper function called
toHex()
is added to theByteArray
class.