anchor.diff:           code_change/3
           ]).
   
  -% Internal API
  +%% Internal API
   -export([handle_message/3]).
   
   -record(state, {handlers}).
  
positive.code: 
  -export([do_handle/3]).
  
  % Gen server hooks
  -export([init/1,
           handle_call/3,
           handle_cast/2,
  
negative.code: %% @doc Start the handler registry process.
  -spec start_link() -> any().
  start_link() ->
      gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
  
  %% @doc Register a record handler.
  -spec register_handler([dns:type()], module()) -> ok.
  register_handler(RecordTypes, Module) ->
      gen_server:call(?MODULE, {register_handler, RecordTypes, Module}).
  
  %% @doc Get all registered handlers along with the DNS types they handle.
  -spec get_handlers() -> [{module(), [dns:type()]}].
  get_handlers() ->
      gen_server:call(?MODULE, {get_handlers}).
  
  
  %% gen_server callbacks
  
  init([]) ->
      {ok, #state{handlers=[]}}.
  
  handle_call({register_handler, RecordTypes, Module}, _, State) ->
      {reply, ok, State#state{handlers = State#state.handlers ++ [{Module, RecordTypes}]}};
  handle_call({get_handlers}, _, State) ->
      {reply, State#state.handlers, State}.
  
  handle_cast(_, State) ->
      {noreply, State}.
  handle_info(_, State) ->
      {noreply, State}.
  terminate(_, _) ->
      erldns_storage:delete_table(handler_registry),
      ok.
  code_change(_PreviousVersion, State, _Extra) ->
      {ok, State}.
  
  %% If the message has trailing garbage just throw the garbage away and continue
  %% trying to process the message.
  handle({trailing_garbage, Message, _}, Context) ->
      handle(Message, Context);
  %% Handle the message, checking to see if it is throttled.
  handle(Message, _Context = {_Data, ClientIP, ServerIP}) when is_record(Message, dns_message) ->
      handle(Message, ClientIP, ServerIP, erldns_query_throttle:throttle(Message, {_Data, ClientIP}));
  %% The message was bad so just return it.
  %% TODO: consider just throwing away the message
  handle(BadMessage, {_, ClientIP, _ServerIP}) ->
      erldns_log:error("Received a bad message: ~p from ~p", [BadMessage, ClientIP]),
      BadMessage.
  
  %% We throttle ANY queries to discourage use of our authoritative name servers
  %% for reflection attacks.
  