anchor.diff: +%%%-------------------------------------------------------------------
  +%%% File    : tracker_delegate.erl
  +%%% Author  : Jesper Louis Andersen <jlouis@succubus.local.domain>
  +%%% Description : Controls the communication with a tracker.
  +%%%
  +%%% Created : 12 Jul 2007 by Jesper Louis Andersen <jlouis@succubus.local.domain>
  +%%%-------------------------------------------------------------------
   -module(tracker_delegate).
  --behaviour(gen_server).
  -
  --export([start_link/1, request_tracker_immediately/1]).
  -
  --export([init/1, handle_cast/2, code_change/3, terminate/2, handle_info/2, handle_call/3]).
  -
  --author("jesper.louis.andersen@gmail.com").
  +
  +-behaviour(gen_fsm).
  +
  +%% API
  +-export([start_link/5, contact_tracker_now/1]).
  +
  +%% gen_fsm callbacks
  +-export([init/1, ready_to_contact/2, waiting_to_contact/2, state_name/3, handle_event/3,
  +	 handle_sync_event/4, handle_info/3, terminate/3, code_change/4]).
  +
  +-record(state, {should_contact_tracker = false,
  +	        state_pid = none,
  +	        url = none,
  +	        infohash = none,
  +	        peer_id = none,
  +	        master_pid = none}).
   
   -record(tracker_request,{port = none,
   			 uploaded = 0,
  
positive.code: -define(SERVER, ?MODULE).
  -define(DEFAULT_REQUEST_TIMEOUT, 180).
  
  %% API
  start_link({Master, StatePid, Url, InfoHash, PeerId}) ->
      gen_server:start_link({local, ?SERVER}, ?MODULE, [{Master, StatePid, Url, InfoHash, PeerId}], []).
  
  request_tracker_immediately(Pid) ->
      gen_server:cast(Pid, tracker_request_now).
  
  %% Callbacks
  init({Master, StatePid, Url, InfoHash, PeerId}) ->
      {ok, {Master, StatePid, Url, InfoHash, PeerId}}.
  
  code_change(_OldVsn, State, _Extra) ->
      {ok, State}.
  
  handle_info(_Foo, State) ->
      {noreply, State}.
  
  terminate(shutdown, _State) ->
      ok.
  
  handle_call(_Call, _Who, S) ->
      {noreply, S}.
  
  
  handle_cast(tracker_request_now, State) ->
      tracker_request(State, none);
  handle_cast(start, State) ->
      tracker_request(State, "started");
  handle_cast(stop, State) ->
      tracker_request(State, "stopped").
  
  %% Internal stuff
  tick_after(Secs) ->
      timer:apply_after(Secs * 1000, self(),
  		      fun () -> request_tracker_immediately(self()) end, []).
  
  build_request_to_send(StatePid) ->
      {data_transfer_amounts, Uploaded, Downloaded, Left} =
  
negative.code: 	    gen_server:cast(Master, {tracker_report, TrackerId, Complete, Incomplete}),
  	    gen_server:cast(Master, {new_ips, NewIPs})
      end,
      {ok, RequestTime}.
  
  perform_get_request(Url, InfoHash, PeerId, Status, Event) ->
      NewUrl = build_tracker_url(Url, Status, InfoHash, PeerId, Event),
      case http:request(NewUrl) of
  	{ok, {{_, 200, _}, _, Body}} ->
  	    {ok, Body}
      end.
  
  build_tracker_url(BaseUrl, TrackerRequest, IHash, PrId, Evt) ->
      %% TODO: Use io_lib:format for this!
      InfoHash = lists:concat(["info_hash=", IHash]),
      PeerId   = lists:concat(["peer_id=", PrId]),
      %% Ignore port for now
  