anchor.diff:      NewState = State#state{download=NewDownload},
       {noreply, NewState};
   
  +handle_info({interest, Change}, State) ->
  +    #state{send_pid=SendPid, local_state=LocalState} = State,
  +    Current = etorrent_peerstate:interested(LocalState),
  +    NewLocalState = if
  +        Current == Change ->
  +            LocalState;
  +        Change == true ->
  +            ok = etorrent_peer_send:interested(SendPid),
  +            etorrent_peerstate:interested(true, LocalState);
  +        Change == false ->
  +            ok = etorrent_peer_send:not_interested(SendPid),
  +            etorrent_peerstate:interested(false, LocalState)
  +    end,
  +    NewState = State#state{local_state=NewLocalState},
  +    {noreply, NewState};
  +            
   handle_info({tcp, _, _}, State) ->
       ?ERR([wrong_controller]),
       {noreply, State};
  
positive.code: handle_message(choke, State) ->
      #state{
          torrent_id=TorrentID,
          fast_extension=FastEnabled,
          remote_request_set=Requests,
          download=Download} = State,
      ok = etorrent_peer_states:set_choke(TorrentID, self()),
      NewState = case FastEnabled of
          true ->
              %% If the Fast Extension is enabled a CHOKE message does
              %% not imply that all outstanding requests are dropped.
              State#state{remote_choked=true};
          false ->
              %% A CHOKE message implies that all outstanding requests has been dropped.
              Chunks = etorrent_rqueue:to_list(Requests),
              ok = etorrent_download:chunks_dropped(Chunks, Download),
              NewRequests = etorrent_rqueue:flush(Requests),
              etorrent_table:foreach_peer(TorrentID, fun try_queue_pieces/1),
              State#state{remote_choked=true, remote_request_set=NewRequests}
      end,
      {ok, NewState};
  handle_message(unchoke, S) ->
      ok = etorrent_peer_states:set_unchoke(S#state.torrent_id, self()),
      try_to_queue_up_pieces(S#state{remote_choked = false});
  handle_message(interested, S) ->
      ok = etorrent_peer_states:set_interested(S#state.torrent_id, self()),
      ok = etorrent_peer_send:check_choke(S#state.send_pid),
      {ok, S};
  handle_message(not_interested, S) ->
      ok = etorrent_peer_states:set_not_interested(S#state.torrent_id, self()),
      ok = etorrent_peer_send:check_choke(S#state.send_pid),
      {ok, S};
  handle_message({request, Index, Offset, Len}, S) ->
      etorrent_peer_send:remote_request(S#state.send_pid, Index, Offset, Len),
      {ok, S};
  handle_message({cancel, Index, Offset, Len}, S) ->
      etorrent_peer_send:cancel(S#state.send_pid, Index, Offset, Len),
      {ok, S};
  handle_message({have, PieceNum}, S) ->
      peer_have(PieceNum, S);
  handle_message({suggest, Idx}, S) ->
      ?INFO([{peer_id, S#state.remote_peer_id}, {suggest, Idx}]),
      {ok, S};
  handle_message(have_none, #state{remote_pieces=PS}=S) when PS =/= unknown ->
      {stop, normal, S};
  handle_message(have_none, #state{fast_extension=true, torrent_id=TorrentID}=S) ->
      {value, NumPieces} = etorrent_torrent:num_pieces(TorrentID),
      Pieceset = etorrent_pieceset:new(NumPieces),
      ok = etorrent_scarcity:add_peer(TorrentID, Pieceset),
      NewState = S#state{
          remote_pieces=Pieceset,
          seeder=false},
      {ok, NewState};
  
  handle_message(have_all, #state{remote_pieces=PS}) when PS =/= unknown ->
      {error, remote_pieces_out_of_band};
  
  handle_message(have_all, #state{fast_extension=true, torrent_id=TorrentID}=S) ->
      {value, NumPieces} = etorrent_torrent:num_pieces(TorrentID),
      AllPieces = lists:seq(0, NumPieces - 1),
      FullSet = etorrent_pieceset:from_list(AllPieces, NumPieces),
      ok = etorrent_scarcity:add_peer(TorrentID, FullSet),
      NewState = S#state{
          remote_pieces=FullSet,
          seeder=true},
      {ok, NewState};
  
  handle_message({bitfield, _}, State) when State#state.remote_pieces /= unknown ->
      #state{socket=Socket, remote_peer_id=RemoteID} = State,
      {ok, {IP, Port}} = inet:peername(Socket),
      etorrent_peer_mgr:enter_bad_peer(IP, Port, RemoteID),
      {error, remote_pieces_out_of_band};
  
  handle_message({bitfield, Bin}, State) ->
      #state{
          torrent_id=TorrentID,
          remote_peer_id=RemoteID} = State,
      {value, Numpieces} = etorrent_torrent:num_pieces(TorrentID),
      Pieceset = etorrent_pieceset:from_binary(Bin, Numpieces),
      ok = etorrent_scarcity:add_peer(TorrentID, Pieceset),
      Left = Numpieces - etorrent_pieceset:size(Pieceset),
      IsSeeder = Left == 0,
      IsSeeder andalso etorrent_table:statechange_peer(self(), seeder),
      NewState = State#state{
          remote_pieces=Pieceset,
          seeder=IsSeeder},
      case etorrent_piece_mgr:check_interest(TorrentID, Pieceset) of
          {interested, _} ->
              statechange_interested(NewState, true),
              {ok, NewState#state{local_interested=true}};
          not_interested ->
              {ok, NewState};
          invalid_piece ->
              {stop, {invalid_piece_2, RemoteID}, State}
      end;
  
  handle_message({piece, Index, Offset, Data}, State) ->
      #state{
          torrent_id=TorrentID,
          download=Download,
          remote_request_set=Requests} = State,
      Length = byte_size(Data),
      NewRequests = case etorrent_rqueue:is_head(Index, Offset, Length, Requests) of
          true ->
              ok = etorrent_download:chunk_fetched(Index, Offset, Length, Download),
              ok = etorrent_io:write_chunk(TorrentID, Index, Offset, Data),
              ok = etorrent_download:chunk_stored(Index, Offset, Length, Download),
              etorrent_rqueue:pop(Requests);
          false ->
              %% Stray piece, we could try to get hold of it but for now we just
              %% throw it on the floor.
              Requests
      end,
      NewState = State#state{remote_request_set=NewRequests},
  	try_to_queue_up_pieces(NewState);
  
  handle_message({extended, _, _}, S) when S#state.extended_messaging == false ->
      %% We do not accept extended messages unless they have been enabled.
      {stop, normal, S};
  handle_message({extended, 0, _BCode}, S) ->
      %% Disable the extended messaging for now,
      %?INFO([{extended_message, etorrent_bcoding:decode(BCode)}]),
      %% We could consider storing the information here, if needed later on,
      %%   but for now we simply ignore that.
      {ok, S};
  handle_message(Unknown, S) ->
      ?WARN([unknown_message, Unknown]),
      {stop, normal, S}.
  
  
  %% @doc Description: Try to queue up requests at the other end.
  %%   Is called in many places with the state as input as the final thing
  %%   it will check if we can queue up pieces and add some if needed.
  %% @end
  try_to_queue_up_pieces(#state { remote_choked = true } = S) ->
      {ok, S};
  try_to_queue_up_pieces(State) ->
      #state{
          send_pid=SendPid,
          remote_pieces=Pieceset,
          remote_request_set=Requests,
          download=Download} = State,
      case etorrent_rqueue:is_low(Requests) of
          false ->
              {ok, State};
          true ->
              Numchunks = etorrent_rqueue:needs(Requests),
              case etorrent_download:request_chunks(Numchunks, Pieceset, Download) of
                  {ok, not_interested} ->
                      statechange_interested(State, false),
                      {ok, State#state{local_interested=false}};
                  {ok, assigned} ->
                      {ok, State};
                  {ok, Chunks} ->
                      NewRequests = etorrent_rqueue:push(Chunks, Requests),
                      [etorrent_peer_send:local_request(SendPid, Chunk)
                      || Chunk <- Chunks],
                      NewState = State#state{remote_request_set=NewRequests},
                      {ok, NewState}
              end
      end.
  
  % @doc Initialize the connection, depending on the way the connection is
  connection_initialize(incoming, S) ->
      case etorrent_proto_wire:complete_handshake(
                      S#state.socket,
                      S#state.info_hash,
                      S#state.local_peer_id) of
          ok -> SendPid = complete_connection_setup(S#state.socket,
                                              S#state.torrent_id,
                                              S#state.extended_messaging),
                NS = S#state { remote_peer_id = none_set,
                              fast_extension = false,
                              send_pid = SendPid},
                {ok, NS};
          {error, stop} -> {stop, normal}
      end;
  connection_initialize(outgoing, S) ->
      SendPid = complete_connection_setup(S#state.socket,
                                          S#state.torrent_id,
                                          S#state.extended_messaging),
      {ok, S#state{send_pid = SendPid}}.
  
  %%--------------------------------------------------------------------
  %% Function: complete_connection_setup(Socket, TorrentId, ExtendedMSG)
  
negative.code:     {ok, State}.
  
  format_status(_Opt, [_Pdict, S]) ->
      #state{remote_config=RemoteConf} = S,
      RemoteID = etorrent_peerconf:peerid(RemoteConf),
      IPPort = case inet:peername(S#state.socket) of
          {ok, IPP} -> IPP;
          {error, Reason} -> {port_error, Reason}
      end,
      Term = [
          {torrent_id,     S#state.torrent_id},
          {remote_peer_id, RemoteID},
          {info_hash,      S#state.info_hash},
          {socket_info,    IPPort}],
      [{data,  [{"State",  Term}]}].
  %%--------------------------------------------------------------------
  
  