Generate URLs for Libravatar and Gravatar avatars
at master 87 lines 2.0 kB view raw
1# SPDX-FileCopyrightText: 2024 Łukasz Niemier <#@hauleth.dev> 2# 3# SPDX-License-Identifier: MPL-2.0 4 5defmodule AwwTest.Dns do 6 use GenServer 7 8 @callback handle_query( 9 String.t(), 10 :inet_req.dns_class(), 11 :inet_req.dns_rr_type() 12 ) :: map() 13 14 def start_link(module: mod) do 15 with {:ok, pid} <- GenServer.start_link(__MODULE__, mod) do 16 {:ok, pid, ns(pid)} 17 end 18 end 19 20 def ns(pid), do: GenServer.call(pid, :name) 21 22 def init(mod) do 23 {:ok, sock} = :gen_udp.open(0, mode: :binary) 24 25 {:ok, %{sock: sock, mod: mod}} 26 end 27 28 def handle_call(:name, _ref, state) do 29 {:ok, name} = :inet.sockname(state.sock) 30 31 {:reply, name, state} 32 end 33 34 def handle_info({:udp, sock, from_ip, from_port, data}, %{sock: sock} = state) do 35 with {:ok, req} <- :inet_dns.decode(data) do 36 req = :inet_dns.msg(req) 37 header = :inet_dns.header(req[:header]) 38 questions = req[:qdlist] 39 40 answers = 41 for q <- questions, 42 query = :inet_dns.dns_query(q), 43 answer <- handle(state, query) do 44 :inet_dns.make_rr(answer) 45 end 46 47 resp_header = 48 :inet_dns.make_header( 49 id: header[:id], 50 aa: false, 51 qr: true, 52 rd: true, 53 ra: true, 54 opcode: :query, 55 rcode: 0 56 ) 57 58 resp = 59 :inet_dns.make_msg( 60 header: resp_header, 61 qdlist: questions, 62 anlist: answers 63 ) 64 65 :gen_udp.send(sock, from_ip, from_port, :inet_dns.encode(resp)) 66 end 67 68 {:noreply, state} 69 end 70 71 defp handle(%{mod: mod}, query) do 72 domain = query[:domain] 73 class = query[:class] 74 type = query[:type] 75 76 resp = 77 try do 78 mod.handle_query(List.to_string(domain), class, type) 79 catch 80 _, _ -> [] 81 end 82 83 for %{ttl: ttl, data: data} <- List.wrap(resp) do 84 [domain: domain, type: type, class: class, ttl: ttl, data: data] 85 end 86 end 87end