]> git.frustrated-labs.net Git - dns-phrasex.git/commitdiff
add DNS server structure
authorAlexander Goussas <[email protected]>
Tue, 27 Jan 2026 03:02:20 +0000 (22:02 -0500)
committerAlexander Goussas <[email protected]>
Tue, 27 Jan 2026 03:02:20 +0000 (22:02 -0500)
.formatter.exs [new file with mode: 0644]
.gitignore [new file with mode: 0644]
README.md [new file with mode: 0644]
lib/dns_phrases.ex [new file with mode: 0644]
lib/dns_phrases/application.ex [new file with mode: 0644]
lib/dns_phrases/server.ex [new file with mode: 0644]
mix.exs [new file with mode: 0644]
test/dns_phrases_test.exs [new file with mode: 0644]
test/test_helper.exs [new file with mode: 0644]

diff --git a/.formatter.exs b/.formatter.exs
new file mode 100644 (file)
index 0000000..d2cda26
--- /dev/null
@@ -0,0 +1,4 @@
+# Used by "mix format"
+[
+  inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
+]
diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..9c04694
--- /dev/null
@@ -0,0 +1,26 @@
+# The directory Mix will write compiled artifacts to.
+/_build/
+
+# If you run "mix test --cover", coverage assets end up here.
+/cover/
+
+# The directory Mix downloads your dependencies sources to.
+/deps/
+
+# Where third-party dependencies like ExDoc output generated docs.
+/doc/
+
+# Ignore .fetch files in case you like to edit your project deps locally.
+/.fetch
+
+# If the VM crashes, it generates a dump, let's ignore it too.
+erl_crash.dump
+
+# Also ignore archive artifacts (built via "mix archive.build").
+*.ez
+
+# Ignore package tarball (built via "mix hex.build").
+dns_phrases-*.tar
+
+# Temporary files, for example, from tests.
+/tmp/
diff --git a/README.md b/README.md
new file mode 100644 (file)
index 0000000..11826dc
--- /dev/null
+++ b/README.md
@@ -0,0 +1,21 @@
+# DnsPhrases
+
+**TODO: Add description**
+
+## Installation
+
+If [available in Hex](https://hex.pm/docs/publish), the package can be installed
+by adding `dns_phrases` to your list of dependencies in `mix.exs`:
+
+```elixir
+def deps do
+  [
+    {:dns_phrases, "~> 0.1.0"}
+  ]
+end
+```
+
+Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc)
+and published on [HexDocs](https://hexdocs.pm). Once published, the docs can
+be found at <https://hexdocs.pm/dns_phrases>.
+
diff --git a/lib/dns_phrases.ex b/lib/dns_phrases.ex
new file mode 100644 (file)
index 0000000..7d7be50
--- /dev/null
@@ -0,0 +1,18 @@
+defmodule DnsPhrases do
+  @moduledoc """
+  Documentation for `DnsPhrases`.
+  """
+
+  @doc """
+  Hello world.
+
+  ## Examples
+
+      iex> DnsPhrases.hello()
+      :world
+
+  """
+  def hello do
+    :world
+  end
+end
diff --git a/lib/dns_phrases/application.ex b/lib/dns_phrases/application.ex
new file mode 100644 (file)
index 0000000..75d94fd
--- /dev/null
@@ -0,0 +1,20 @@
+defmodule DnsPhrases.Application do
+  # See https://hexdocs.pm/elixir/Application.html
+  # for more information on OTP Applications
+  @moduledoc false
+
+  use Application
+
+  @impl true
+  def start(_type, _args) do
+    children = [
+      # TODO: Fetch the port from command line
+      {DnsPhrases.Server, [listen_port: 3069]}
+    ]
+
+    # See https://hexdocs.pm/elixir/Supervisor.html
+    # for other strategies and supported options
+    opts = [strategy: :one_for_one, name: DnsPhrases.Supervisor]
+    Supervisor.start_link(children, opts)
+  end
+end
diff --git a/lib/dns_phrases/server.ex b/lib/dns_phrases/server.ex
new file mode 100644 (file)
index 0000000..d022ca0
--- /dev/null
@@ -0,0 +1,29 @@
+defmodule DnsPhrases.Server do
+  use GenServer
+
+  defmodule State do
+    defstruct([:socket])
+  end
+
+  def start_link(opts) do
+    listen_port = Keyword.fetch!(opts, :listen_port)
+    GenServer.start_link(__MODULE__, listen_port, opts)
+  end
+
+  @impl GenServer
+  def init(listen_port) do
+    {:ok, socket} = :gen_udp.open(listen_port, mode: :binary, active: true)
+    {:ok, %State{socket: socket}}
+  end
+
+  @impl GenServer
+  def handle_info(
+        {:udp, socket, _ip, _port, data},
+        %State{socket: socket} = state
+      ) do
+    # TODO 1: Fetch random phrase
+    # TODO 2: Assemble DNS response as a TXT record containing the frame
+    # TODO 3: Reply to our client
+    {:noreply, state}
+  end
+end
diff --git a/mix.exs b/mix.exs
new file mode 100644 (file)
index 0000000..d7c6c26
--- /dev/null
+++ b/mix.exs
@@ -0,0 +1,29 @@
+defmodule DnsPhrases.MixProject do
+  use Mix.Project
+
+  def project do
+    [
+      app: :dns_phrases,
+      version: "0.1.0",
+      elixir: "~> 1.17",
+      start_permanent: Mix.env() == :prod,
+      deps: deps()
+    ]
+  end
+
+  # Run "mix help compile.app" to learn about applications.
+  def application do
+    [
+      extra_applications: [:logger],
+      mod: {DnsPhrases.Application, []}
+    ]
+  end
+
+  # Run "mix help deps" to learn about dependencies.
+  defp deps do
+    [
+      # {:dep_from_hexpm, "~> 0.3.0"},
+      # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}
+    ]
+  end
+end
diff --git a/test/dns_phrases_test.exs b/test/dns_phrases_test.exs
new file mode 100644 (file)
index 0000000..e550341
--- /dev/null
@@ -0,0 +1,8 @@
+defmodule DnsPhrasesTest do
+  use ExUnit.Case
+  doctest DnsPhrases
+
+  test "greets the world" do
+    assert DnsPhrases.hello() == :world
+  end
+end
diff --git a/test/test_helper.exs b/test/test_helper.exs
new file mode 100644 (file)
index 0000000..869559e
--- /dev/null
@@ -0,0 +1 @@
+ExUnit.start()