]> git.frustrated-labs.net Git - dns-phrasex.git/commitdiff
feat: parse incoming dns question
authorAlexander Goussas <[email protected]>
Sat, 31 Jan 2026 20:48:18 +0000 (15:48 -0500)
committerAlexander Goussas <[email protected]>
Sat, 31 Jan 2026 20:48:18 +0000 (15:48 -0500)
lib/dns_phrases/message.ex [new file with mode: 0644]
lib/dns_phrases/message/parser.ex [new file with mode: 0644]
lib/dns_phrases/server.ex

diff --git a/lib/dns_phrases/message.ex b/lib/dns_phrases/message.ex
new file mode 100644 (file)
index 0000000..e0ac29c
--- /dev/null
@@ -0,0 +1,8 @@
+defmodule DnsPhrases.Message do
+  defstruct [:op, tid: 0]
+
+  @typedoc """
+  A message received from a client.
+  """
+  @type t :: %DnsPhrases.Message{op: integer, tid: integer}
+end
diff --git a/lib/dns_phrases/message/parser.ex b/lib/dns_phrases/message/parser.ex
new file mode 100644 (file)
index 0000000..835ab73
--- /dev/null
@@ -0,0 +1,37 @@
+defmodule DnsPhrases.Message.Parser do
+  alias DnsPhrases.Message
+
+  @spec parse(bitstring) :: DnsPhrases.Message.t()
+
+  def parse(<<
+        tid::16,
+        0::1,
+        _flags::15,
+        1::integer-size(16),
+        _number_of_answers::16,
+        _authority_rrs::16,
+        _additional_rrs::16,
+        data::bitstring
+      >>) do
+    op = parse_question(data)
+    %Message{tid: tid, op: op}
+  end
+
+  @spec parse_question(bitstring) :: list
+  def parse_question(data), do: parse_question(data, []) |> Enum.reverse()
+
+  @spec parse_question(bitstring, list) :: list
+  defp parse_question(
+         <<n::integer-size(8), data::bitstring-size(n * 8), 0::8, _rest::bitstring>>,
+         parts
+       ) do
+    [data | parts]
+  end
+
+  defp parse_question(
+         <<n::integer-size(8), data::bitstring-size(n * 8), rest::bitstring>>,
+         parts
+       ) do
+    parse_question(rest, [data | parts])
+  end
+end
index d022ca03441e8d72f5a837d95c476ac0628655b0..fcb5d4a1b2facd68063c32fe455b58ebeef620b3 100644 (file)
@@ -1,6 +1,8 @@
 defmodule DnsPhrases.Server do
   use GenServer
 
+  alias DnsPhrases.Message.Parser
+
   defmodule State do
     defstruct([:socket])
   end
@@ -21,7 +23,9 @@ defmodule DnsPhrases.Server do
         {:udp, socket, _ip, _port, data},
         %State{socket: socket} = state
       ) do
-    # TODO 1: Fetch random phrase
+    # TODO 1: Parse DNS message
+    Parser.parse(data)
+
     # TODO 2: Assemble DNS response as a TXT record containing the frame
     # TODO 3: Reply to our client
     {:noreply, state}