anchor.diff:      {stop, {state_inconsistent, {connid_expired, SN, S}}, idle};
   handle_info({announce_timeout, N, Tid}, has_conn,
   	    #state { response = R, conn_id = ConnId} = S) ->
  +    etorrent_udp_tracker_mgr:unreg_tr_id(Tid),
       case proplists:lookup(Tid, R) of
   	none ->
   	    %% Stray
  
positive.code: -module(etorrent_udp_tracker).
  
  -include("types.hrl").
  -behaviour(gen_fsm).
  
  %% API
  -export([start_link/1, announce/2, announce/3, msg/2]).
  
  %% gen_fsm callbacks
  -export([init/1, idle/2, idle/3, request_conn/2, request_conn/3, has_conn/2, has_conn/3,
  
negative.code: 
  -record(state, { conn_id = none,
  		 response = [],
  	         announce_stack = [] }).
  
  %%====================================================================
  -spec start_link({ip(), port()}) -> {ok, pid()}.
  start_link(Tracker) ->
      gen_fsm:start_link(?MODULE, [Tracker], []).
  
  
  announce(Pid, Proplist) ->
      announce(Pid, Proplist, timer:seconds(60)).
  
  %% TODO: consider changing this to the gproc call rather than Pid
  announce(Pid, Proplist, Timeout) ->
      %% TODO: Consider hauling the TRef with us as well so we can cancel the timer
      TRef = erlang:send_after(Timeout, self(), announce_timeout),
      gen_fsm:send_event(Pid, {announce, self(), Proplist, TRef}),
      {ok, TRef}.
  
  %%====================================================================
  %% Retrieve a message from the socket.
  msg(Pid, M) ->
      gen_fsm:send_event(Pid, {msg, M}).
  
  init([Tracker]) ->
      gproc:add_local_name({udp_tracker, Tracker}),
      {ok, idle, #state{}, timer:seconds(3600)}.
  
  idle({msg, {_TID, {conn_response, _ConnID}}}, S) ->
      {next_state, idle, S, timer:seconds(3600)};
  idle({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, idle, S#state { response = PL }, timer:seconds(3600)};
  %% The idle state is when we have no outstanding requests running with the server
  idle({announce, Requestor, PL, R}, #state { announce_stack = Q } = S) ->
      Tid = request_connid(0),
      {next_state, request_conn, S#state { announce_stack = [{announce, Requestor, PL, R} | Q],
  				         conn_id = {req, Tid} }};
  idle(Event, S) ->
      ?INFO([unknown_msg, idle, Event, ?MODULE]),
      {next_state, idle, S, timer:seconds(3600)}.
  
  %% The request_conn state is when we have requested a connection ID from the server
  request_conn({msg, {TID, {conn_response, ConnID}}}, S) ->
  