简化dns的查询逻辑

This commit is contained in:
anlicheng 2025-12-12 15:40:33 +08:00
parent d33fe7e540
commit a32f00a1d8
3 changed files with 66 additions and 58 deletions

View File

@ -73,64 +73,13 @@ handle_call(_Request, _From, State = #state{}) ->
{noreply, NewState :: #state{}, timeout() | hibernate} |
{stop, Reason :: term(), NewState :: #state{}}).
handle_cast(handle, State = #state{socket = Sock, src_ip = SrcIp, src_port = SrcPort, packet = Packet}) ->
case dns:decode_message(Packet) of
QueryMsg = #dns_message{qc = 1, questions = [Question = #dns_query{name = QName, type = QType, class = QClass}|_]} ->
%%
case search_inbuilt_domain(QName) of
{ok, Ip} ->
Answer = #dns_rr {
name = QName,
type = QType,
class = QClass,
ttl = 300,
data = #dns_rrdata_a {
ip = Ip
}
},
RespMsg = QueryMsg#dns_message{
qr = true,
ra = true,
anc = 1,
auc = 0,
adc = 0,
answers = [Answer],
authority = [],
additional = []
},
gen_udp:send(Sock, SrcIp, SrcPort, dns:encode_message(RespMsg)),
{stop, normal, State};
error ->
case dns_cache:lookup(Question) of
{hit, Cache} ->
lager:debug("[dns_handler] question: ~p, hit cache answers: ~p", [Question, Cache#dns_cache.answers]),
RespMsg = build_response(QueryMsg, Cache),
gen_udp:send(Sock, SrcIp, SrcPort, dns:encode_message(RespMsg)),
{stop, normal, State};
miss ->
lager:debug("[dns_handler] cache is miss"),
Ref = make_ref(),
forward_to_upstream(Ref, Packet, QueryMsg),
receive
{dns_resolver_reply, Ref, Resp} ->
case dns:decode_message(Resp) of
RespMsg = #dns_message{answers = Answers} ->
lager:debug("[dns_handler] get a response answers: ~p", [Answers]),
dns_cache:insert(Question, RespMsg),
case resolver(Packet) of
{ok, Resp} ->
gen_udp:send(Sock, SrcIp, SrcPort, Resp);
Other ->
lager:debug("[dns_handler] parse reply get error: ~p", [Other])
{error, Reason} ->
lager:debug("[dns_handler] resolver get error: ~p", [Reason])
end,
{stop, normal, State}
after 5000 ->
{stop, normal, State}
end
end
end;
Other ->
lager:warning("[dns_handler] decode dns query get error: ~p", [Other]),
{stop, normal, State}
end.
{stop, normal, State}.
%% @private
%% @doc Handling all non call/cast messages
@ -163,6 +112,63 @@ code_change(_OldVsn, State = #state{}, _Extra) ->
%%% Internal functions
%%%===================================================================
-spec resolver(Packet :: binary()) -> {ok, Resp :: binary()} | {error, Reason :: any()}.
resolver(Packet) when is_binary(Packet) ->
resolver0(Packet, dns:decode_message(Packet)).
resolver0(Packet, QueryMsg = #dns_message{qc = 1, questions = [Question = #dns_query{name = QName, type = QType, class = QClass}|_]}) ->
%%
case search_inbuilt_domain(QName) of
{ok, Ip} ->
Answer = #dns_rr {
name = QName,
type = QType,
class = QClass,
ttl = 300,
data = #dns_rrdata_a {
ip = Ip
}
},
RespMsg = QueryMsg#dns_message{
qr = true,
ra = true,
anc = 1,
auc = 0,
adc = 0,
answers = [Answer],
authority = [],
additional = []
},
{ok, dns:encode_message(RespMsg)};
error ->
case dns_cache:lookup(Question) of
{hit, Cache} ->
lager:debug("[dns_handler] question: ~p, hit cache answers: ~p", [Question, Cache#dns_cache.answers]),
RespMsg = build_response(QueryMsg, Cache),
{ok, dns:encode_message(RespMsg)};
miss ->
lager:debug("[dns_handler] cache is miss"),
Ref = make_ref(),
forward_to_upstream(Ref, Packet, QueryMsg),
receive
{dns_resolver_reply, Ref, Resp} ->
case dns:decode_message(Resp) of
RespMsg = #dns_message{answers = Answers} ->
lager:debug("[dns_handler] get a response answers: ~p", [Answers]),
dns_cache:insert(Question, RespMsg),
{ok, Resp};
Error ->
lager:debug("[dns_handler] parse reply get error: ~p", [Error]),
Error
end
after 5000 ->
{error, timeout}
end
end
end;
resolver0(_, Error) ->
lager:warning("[dns_handler] decode dns query get error: ~p", [Error]),
Error.
-spec forward_to_upstream(Ref :: reference(), Request :: binary(), QueryMsg :: #dns_message{}) -> no_return().
forward_to_upstream(Ref, Request, QueryMsg) ->
ReceiverPid = self(),

View File

@ -8,6 +8,7 @@
sync,
lager,
dns_erlang,
pkt,
poolboy,
kernel,
stdlib

View File

@ -2,6 +2,7 @@
{deps, [
{dns_erlang, ".*", {git, "https://github.com/dnsimple/dns_erlang.git", {tag, "v4.4.0"}}},
{poolboy, ".*", {git, "https://github.com/devinus/poolboy.git", {tag, "1.5.1"}}},
{pkt, ".*", {git, "https://github.com/msantos/pkt.git", {tag, "0.6.0"}}},
{sync, ".*", {git, "https://github.com/rustyio/sync.git", {branch, "master"}}},
{parse_trans, ".*", {git, "https://github.com/uwiger/parse_trans", {tag, "3.0.0"}}},
{lager, ".*", {git,"https://github.com/erlang-lager/lager.git", {tag, "3.9.2"}}}