anchor.diff:  -module(etorrent_udp_tracker).
   
   -include("types.hrl").
  +-include("log.hrl").
   -behaviour(gen_fsm).
   
   %% API
  --export([start_link/1, announce/2, announce/3, msg/2]).
  +-export([start_link/1, announce/2, announce/3]).
  +
  +%% Internally used calls
  +-export([msg/2]).
   
   %% gen_fsm callbacks
   -export([init/1, idle/2, idle/3, request_conn/2, request_conn/3, has_conn/2, has_conn/3,
  
positive.code:     {stop, {state_inconsistent, {connid_expired, SN, S}}, idle};
  handle_info({announce_timeout, N, Tid}, has_conn,
  	    #state { response = R, conn_id = ConnId} = S) ->
      case proplists:lookup(Tid, R) of
  	none ->
  	    %% Stray
  
negative.code:     erlang:send_after(timer:seconds(60), self(), connid_expired),
      ARes = announce_requests(ConnID, S#state.announce_stack),
      {next_state, has_conn, #state { conn_id = ConnID,
  				    announce_stack = [],
  				    response = S#state.response ++ ARes }};
  request_conn({msg, {TID, {announce_response, Peers, Status}}}, #state { response = R} = S) ->
      announce_reply(Peers, Status, proplists:lookup(TID, R)),
      PL = proplists:delete(TID, R),
      {next_state, request_conn, S#state { response = PL }};
  request_conn({announce, Requestor, PL, R}, #state { announce_stack = Q } = S) ->
      {next_state, request_conn, S#state { announce_stack = [{announce, Requestor, PL, R} | Q]}};
  request_conn(Event, S) ->
      ?INFO([unknown_msg, request_conn, Event, ?MODULE]),
      {next_state, request_conn, S}.
  
  %% The has_conn is when we currently have a live conn ID from the server
  has_conn({announce, _, _, _} = M, #state { response = Resp } = S) ->
      Ares = announce_requests(S#state.conn_id, [M]),
      {next_state, has_conn, S#state { response = Ares ++ Resp }};
  has_conn({msg, {TID, {announce_response, Peers, Status}}}, #state { response = R} = S) ->
      announce_reply(Peers, Status, proplists:lookup(TID, R)),
      PL = proplists:delete(TID, R),
      {next_state, has_conn, S#state { response = PL }};
  has_conn(Event, S) ->
      ?INFO([unknown_msg, has_conn, Event, ?MODULE]),
      {next_state, has_conn, S}.
  
  idle(_Event, _F, S) ->
      {reply, ok, idle, S}.
  