| defmodule Plasusible.Test.Support.DNSServer do |
| @moduledoc """ |
| A simple DNS server that responds to TXT queries with fixed sample values. |
| """ |
|
|
| def start(fixed_response) do |
| {:ok, socket} = :gen_udp.open(0, [:binary, active: true, ip: {0, 0, 0, 0}]) |
| {:ok, port} = :inet.port(socket) |
| child = spawn(fn -> loop(socket, fixed_response) end) |
| :ok = :gen_udp.controlling_process(socket, child) |
| {:ok, port} |
| end |
|
|
| defp loop(socket, fixed_response) do |
| receive do |
| {:udp, _socket, client_ip, client_port, query} -> |
| response = build_response(query, fixed_response) |
| :gen_udp.send(socket, client_ip, client_port, response) |
| loop(socket, fixed_response) |
| end |
| end |
|
|
| defp build_response(query, response) do |
| <<transaction_id::16, _flags::16, qdcount::16, _rest::binary>> = query |
|
|
| header = << |
| |
| transaction_id::16, |
| |
| 0b10000100_00000000::16, |
| |
| qdcount::16, |
| |
| 1::16, |
| |
| 0::16, |
| |
| 0::16 |
| >> |
|
|
| <<_header::binary-size(12), question::binary>> = query |
| txt_data = encode_txt_data(response) |
|
|
| answer = << |
| |
| 0xC00C::16, |
| |
| 16::16, |
| |
| 1::16, |
| |
| 60::32, |
| byte_size(txt_data)::16, |
| txt_data::binary |
| >> |
|
|
| [header, question, answer] |
| end |
|
|
| defp encode_txt_data(txt_value) do |
| <<byte_size(txt_value)::8, txt_value::binary>> |
| end |
| end |
|
|