Skip to content

Commit

Permalink
UDP and TCP servers now are gen_servers and replace the erldns_server…
Browse files Browse the repository at this point in the history
…. Functions that remained there were moved to erldns_handler.
  • Loading branch information
aeden committed Aug 21, 2012
1 parent 2955aec commit be3574a
Show file tree
Hide file tree
Showing 9 changed files with 217 additions and 166 deletions.
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -21,7 +21,7 @@ Currently the MySQL responder uses the PowerDNS schema. See "http://doc.powerdns

Launch directly:

erl -config erldns.config -pa ./ebin ./deps/mysql/ebin ./deps/poolboy/ebin ./deps/dns/ebin -s erldns
erl -config erldns.config -pa ./ebin ./deps/lager/ebin ./deps/mysql/ebin ./deps/poolboy/ebin ./deps/dns/ebin -s erldns

Or use Foreman:

Expand Down
9 changes: 5 additions & 4 deletions ebin/erldns.app
@@ -1,9 +1,10 @@
{application,erldns,
[{description,"Erlang Authoritative DNS Server"},
{vsn,"49ba860"},
{modules,[erldns,erldns_app,erldns_fake_responder,
{vsn,"ba2e283"},
{modules,[erldns,erldns_app,erldns_handler,
erldns_mysql_responder,erldns_packet_cache,
erldns_records,erldns_server,erldns_sup]},
{registered,[erldns_server]},
erldns_records,erldns_sup,erldns_tcp_server,
erldns_udp_server]},
{registered,[erldns_udp_server,erldns_tcp_server]},
{mod,{erldns_app,[]}},
{applications,[kernel,stdlib]}]}.
File renamed without changes.
6 changes: 4 additions & 2 deletions src/erldns.app.src
Expand Up @@ -3,11 +3,13 @@
{vsn, git},
{modules, [erldns,
erldns_app,
erldns_server,
erldns_handler,
erldns_udp_server,
erldns_tcp_server,
erldns_unpack,
erldns_pack,
erldns_records]},
{registered, [erldns_server]},
{registered, [erldns_udp_server, erldns_tcp_server]},
{mod, { erldns_app, []}},
{applications, [kernel, stdlib]}]}.

55 changes: 55 additions & 0 deletions src/erldns_handler.erl
@@ -0,0 +1,55 @@
-module(erldns_handler).

-include("dns_records.hrl").

% Protected API
-export([handle/1]).

%% Handle the decoded message
handle(DecodedMessage) ->
Questions = DecodedMessage#dns_message.questions,
case erldns_packet_cache:get(Questions) of
{ok, Answers} ->
lager:info("Packet cache hit"),
build_response(Answers, DecodedMessage);
{error, _} ->
lager:info("Packet cache miss"),
Response = answer_questions(Questions, DecodedMessage),
erldns_packet_cache:put(Questions, Response#dns_message.answers),
Response
end.

%% Answer the questions and return an updated copy of the given
%% Response.
answer_questions([], Response) ->
Response;
answer_questions([Q|Rest], Response) ->
lager:info("Question: ~p~n", [Q]),
NewResponse = answer_question(Q, Response),
answer_questions(Rest, NewResponse).

%% Add answers for a specific request to the given Response and return
%% an updated copy of the Response.
answer_question(Q, Response) ->
[Name, Type] = [Q#dns_query.name, Q#dns_query.type],

ResponderModules = case application:get_env(erldns, responders) of
{ok, RM} -> RM;
_ -> [erldns_mysql_responder]
end,

Responders = lists:map(fun(M) -> fun M:answer/2 end, ResponderModules),

Answers = lists:flatten(
lists:map(
fun(F) ->
F(Name, dns:type_name(Type))
end, Responders)),

build_response(Answers, Response).

%% Populate a response with the given answers
build_response(Answers, Response) ->
NewResponse = Response#dns_message{anc = length(Answers), qr=true, aa = true, answers = Answers},
lager:info("Response: ~p~n", [NewResponse]),
NewResponse.
155 changes: 0 additions & 155 deletions src/erldns_server.erl

This file was deleted.

11 changes: 7 additions & 4 deletions src/erldns_sup.erl
Expand Up @@ -9,14 +9,17 @@

-define(SUPERVISOR, ?MODULE).

%% Helper macro for declaring children of supervisor
-define(CHILD(I, Type, Args), {I, {I, start_link, Args}, permanent, 5000, Type, [I]}).

%% Public API
start_link() ->
supervisor:start_link({local, ?SUPERVISOR}, ?MODULE, []).

init(_Args) ->
Procs = [
{erldns_server, {erldns_server, start_link, []},
permanent, 5000, worker, [erldns_server]},
{erldns_packet_cache, {erldns_packet_cache, start_link, []},
permanent, 5000, worker, [erldns_packet_cache]}
?CHILD(erldns_packet_cache, worker, []),
?CHILD(erldns_udp_server, worker, []),
?CHILD(erldns_tcp_server, worker, [])
],
{ok, {{one_for_one, 5, 10}, Procs}}.
74 changes: 74 additions & 0 deletions src/erldns_tcp_server.erl
@@ -0,0 +1,74 @@
-module(erldns_tcp_server).

-behavior(gen_server).

% API
-export([start_link/0]).

% Gen server hooks
-export([init/1,
handle_call/3,
handle_cast/2,
handle_info/2,
terminate/2,
code_change/3
]).

-define(SERVER, ?MODULE).

-record(state, {}).

%% Public API
start_link() ->
gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).

%% gen_server hooks
init(_Args) ->
{ok, Port} = application:get_env(erldns, port),
spawn(fun() -> start(Port) end),
{ok, #state{}}.
handle_call(_Request, _From, State) ->
{ok, State}.
handle_cast(_Message, State) ->
{noreply, State}.
handle_info(_Message, State) ->
{noreply, State}.
terminate(_Reason, _State) ->
ok.
code_change(_PreviousVersion, State, _Extra) ->
{ok, State}.

%% Internal API
start(Port) ->
random:seed(erlang:now()),
case gen_tcp:listen(Port, [binary, {packet, 0}, {active, true}]) of
{ok, LSocket} ->
lager:info("TCP server opened listener: ~p~n", [LSocket]),
loop(LSocket);
{error, eacces} ->
lager:error("Failed to open TCP listener. Need to run as sudo?"),
{error, eacces}
end.

%% Loop for accepting TCP requests
loop(LSocket) ->
{ok, Socket} = gen_tcp:accept(LSocket),
lager:info("TCP server opened socket: ~p~n", [Socket]),
receive
{tcp, Socket, Bin} ->
io:format("Received TCP Request~n"),
spawn(fun() -> handle_dns_query(Socket, Bin) end),
loop(LSocket)
end.

%% Handle DNS query that comes in over TCP
handle_dns_query(Socket, Packet) ->
<<Len:16, Bin/binary>> = Packet,
lager:info("TCP Message received, len: ~p~n", [Len]),
DecodedMessage = dns:decode_message(Bin),
NewResponse = erldns_handler:handle(DecodedMessage),
BinReply = dns:encode_message(NewResponse),
BinLength = byte_size(BinReply),
TcpBinReply = <<BinLength:16, BinReply/binary>>,
gen_tcp:send(Socket, TcpBinReply),
gen_tcp:close(Socket).

0 comments on commit be3574a

Please sign in to comment.