2023-06-13 02:36:32 +02:00
|
|
|
open Types
|
|
|
|
open Utils
|
|
|
|
|
|
|
|
let parse_header reader =
|
2023-06-14 16:34:49 +02:00
|
|
|
let max_size = 6 in
|
2023-06-14 18:41:43 +02:00
|
|
|
match List.init max_size (fun offset -> unpack_short_be reader.data (offset * 2)) with
|
2023-06-13 02:36:32 +02:00
|
|
|
| [ id; flags; num_questions; num_answers; num_authorities; num_additionals ] ->
|
2023-06-14 18:41:43 +02:00
|
|
|
( { reader with pointer = reader.pointer + (max_size * 2) }
|
2023-06-14 16:34:49 +02:00
|
|
|
, { id; flags; num_questions; num_answers; num_authorities; num_additionals } )
|
|
|
|
| _ -> failwith "Invalid number of fields"
|
|
|
|
;;
|
|
|
|
|
2023-06-14 16:37:30 +02:00
|
|
|
let rec parse_question reader =
|
2023-06-19 19:38:35 +02:00
|
|
|
let name, offset_name = decode_name reader in
|
2023-06-14 18:41:43 +02:00
|
|
|
let data = bytes_forward reader.data (reader.pointer + offset_name) in
|
2023-06-14 16:54:55 +02:00
|
|
|
let max_size = 2 in
|
2023-06-14 18:41:43 +02:00
|
|
|
match List.init max_size (fun offset -> unpack_short_be data (offset * 2)) with
|
|
|
|
| [ type_; class_ ] ->
|
|
|
|
( { reader with pointer = reader.pointer + offset_name + (max_size * 2) }
|
|
|
|
, { name; type_; class_ } )
|
2023-06-14 16:37:30 +02:00
|
|
|
| _ -> failwith "Invalid number of fields"
|
|
|
|
|
2023-06-19 19:38:35 +02:00
|
|
|
and decode_name reader =
|
2023-06-14 16:34:49 +02:00
|
|
|
let rec read_parts parts pos =
|
2023-06-14 18:41:43 +02:00
|
|
|
let length = int_of_char (Bytes.get reader.data (reader.pointer + pos)) in
|
2023-06-14 16:34:49 +02:00
|
|
|
if length = 0
|
|
|
|
then 1, parts
|
2023-06-14 18:52:17 +02:00
|
|
|
else if length land 0b1100_0000 <> 0
|
|
|
|
then (
|
|
|
|
let decoded_name = decode_compressed_name reader length in
|
2023-06-14 18:53:13 +02:00
|
|
|
2, decoded_name :: parts)
|
2023-06-14 16:34:49 +02:00
|
|
|
else (
|
2023-06-14 18:41:43 +02:00
|
|
|
let part = Bytes.sub_string reader.data (reader.pointer + pos + 1) length in
|
2023-06-14 16:34:49 +02:00
|
|
|
let last_length, parts' = read_parts (parts @ [ part ]) (pos + 1 + length) in
|
|
|
|
last_length + length + 1, parts')
|
|
|
|
in
|
|
|
|
let offset, parts = read_parts [] 0 in
|
2023-06-14 18:41:43 +02:00
|
|
|
String.to_bytes (String.concat "." parts), offset
|
2023-06-14 18:52:17 +02:00
|
|
|
|
2023-06-19 19:38:35 +02:00
|
|
|
and decode_compressed_name reader length =
|
|
|
|
let pointer =
|
|
|
|
(length land 0b0011_1111) + int_of_char (Bytes.get reader.data (reader.pointer + 1))
|
|
|
|
in
|
|
|
|
String.of_bytes (fst (decode_name { reader with pointer }))
|
2023-06-14 16:34:49 +02:00
|
|
|
;;
|
2023-06-14 16:54:55 +02:00
|
|
|
|
2023-06-14 18:52:17 +02:00
|
|
|
let parse_record reader =
|
2023-06-19 20:03:27 +02:00
|
|
|
let name, offset_name = decode_name reader in
|
|
|
|
let data = bytes_forward reader.data (offset_name + reader.pointer) in
|
|
|
|
{ name
|
|
|
|
; type_ = unpack_short_be data 0
|
|
|
|
; class_ = unpack_short_be data 2
|
|
|
|
; ttl = unpack_int_be data 4
|
|
|
|
; data = Bytes.sub data 10 (unpack_short_be data 8)
|
|
|
|
}
|
2023-06-14 16:54:55 +02:00
|
|
|
;;
|