/*
* Created on 14-Feb-2005
* Created by Paul Gardner
* Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* AELITIS, SAS au capital de 46,603.30 euros
* 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
*
*/
package org.gudy.azureus2.core3.tracker.client.impl.dht;
import java.net.URL;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import org.gudy.azureus2.core3.internat.MessageText;
import org.gudy.azureus2.core3.logging.*;
import org.gudy.azureus2.core3.torrent.TOTorrent;
import org.gudy.azureus2.core3.torrent.TOTorrentAnnounceURLSet;
import org.gudy.azureus2.core3.torrent.TOTorrentException;
import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncer;
import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncerDataProvider;
import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncerException;
import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncerListener;
import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncerResponse;
import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncerResponsePeer;
import org.gudy.azureus2.core3.tracker.client.impl.TRTrackerAnnouncerHelper;
import org.gudy.azureus2.core3.tracker.client.impl.TRTrackerAnnouncerImpl;
import org.gudy.azureus2.core3.tracker.client.impl.TRTrackerAnnouncerResponseImpl;
import org.gudy.azureus2.core3.tracker.client.impl.TRTrackerAnnouncerResponsePeerImpl;
import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.core3.util.HashWrapper;
import org.gudy.azureus2.core3.util.IndentWriter;
import org.gudy.azureus2.core3.util.SystemTime;
import org.gudy.azureus2.core3.util.TorrentUtils;
import org.gudy.azureus2.plugins.clientid.ClientIDException;
import org.gudy.azureus2.plugins.download.DownloadAnnounceResult;
import org.gudy.azureus2.plugins.download.DownloadAnnounceResultPeer;
import org.gudy.azureus2.pluginsimpl.local.clientid.ClientIDManagerImpl;
import com.aelitis.azureus.core.tracker.TrackerPeerSource;
/**
* @author parg
*
*/
public class
TRTrackerDHTAnnouncerImpl
implements TRTrackerAnnouncerHelper
{
public final static LogIDs LOGID = LogIDs.TRACKER;
private TOTorrent torrent;
private HashWrapper torrent_hash;
private TRTrackerAnnouncerImpl.Helper helper;
private byte[] data_peer_id;
private String tracker_status_str;
private long last_update_time;
private int state = TS_INITIALISED;
private TRTrackerAnnouncerResponseImpl last_response;
private boolean manual;
public
TRTrackerDHTAnnouncerImpl(
TOTorrent _torrent,
String[] _networks,
boolean _manual,
TRTrackerAnnouncerImpl.Helper _helper )
throws TRTrackerAnnouncerException
{
torrent = _torrent;
manual = _manual;
helper = _helper;
try{
torrent_hash = torrent.getHashWrapper();
}catch( TOTorrentException e ){
Debug.printStackTrace(e);
}
try{
data_peer_id = ClientIDManagerImpl.getSingleton().generatePeerID( torrent, false );
}catch( ClientIDException e ){
throw( new TRTrackerAnnouncerException( "TRTrackerAnnouncer: Peer ID generation fails", e ));
}
last_response =
new TRTrackerAnnouncerResponseImpl(
torrent.getAnnounceURL(),
torrent_hash,
TRTrackerAnnouncerResponse.ST_OFFLINE, 0, "Initialising" );
tracker_status_str = MessageText.getString("PeerManager.status.checking") + "...";
}
public void
setAnnounceDataProvider(
TRTrackerAnnouncerDataProvider provider )
{
}
public boolean
isManual()
{
return( manual );
}
public TOTorrent
getTorrent()
{
return( torrent );
}
public URL
getTrackerURL()
{
return( TorrentUtils.getDecentralisedURL( torrent ));
}
public void
setTrackerURL(
URL url )
{
Debug.out( "Not implemented" );
}
public TOTorrentAnnounceURLSet[]
getAnnounceSets()
{
return( new TOTorrentAnnounceURLSet[]{
torrent.getAnnounceURLGroup().createAnnounceURLSet(
new URL[]{ TorrentUtils.getDecentralisedURL( torrent )})} );
}
public void
resetTrackerUrl(
boolean shuffle )
{
}
public void
setIPOverride(
String override )
{
}
public void
clearIPOverride()
{
}
public int
getPort()
{
return(0);
}
public byte[]
getPeerId()
{
return( data_peer_id );
}
public void
setRefreshDelayOverrides(
int percentage )
{
}
public int
getTimeUntilNextUpdate()
{
long elapsed = (SystemTime.getCurrentTime() - last_update_time)/1000;
return( (int)(last_response.getTimeToWait()-elapsed));
}
public int
getLastUpdateTime()
{
return( (int)(last_update_time/1000));
}
public void
update(
boolean force )
{
state = TS_DOWNLOADING;
}
public void
complete(
boolean already_reported )
{
state = TS_COMPLETED;
}
public void
stop(
boolean for_queue )
{
state = TS_STOPPED;
}
public void
destroy()
{
}
public int
getStatus()
{
return( state );
}
public String
getStatusString()
{
return( tracker_status_str );
}
public TRTrackerAnnouncer
getBestAnnouncer()
{
return( this );
}
public TRTrackerAnnouncerResponse
getLastResponse()
{
return( last_response );
}
public boolean
isUpdating()
{
return( false );
}
public long
getInterval()
{
return( -1 );
}
public long
getMinInterval()
{
return( -1 );
}
public void
refreshListeners()
{
}
public void
setAnnounceResult(
DownloadAnnounceResult result )
{
last_update_time = SystemTime.getCurrentTime();
TRTrackerAnnouncerResponseImpl response;
if ( result.getResponseType() == DownloadAnnounceResult.RT_ERROR ){
tracker_status_str = MessageText.getString("PeerManager.status.error");
String reason = result.getError();
if ( reason != null ){
tracker_status_str += " (" + reason + ")";
}
response = new TRTrackerAnnouncerResponseImpl(
result.getURL(),
torrent_hash,
TRTrackerAnnouncerResponse.ST_OFFLINE,
result.getTimeToWait(),
reason );
}else{
DownloadAnnounceResultPeer[] ext_peers = result.getPeers();
TRTrackerAnnouncerResponsePeerImpl[] peers = new TRTrackerAnnouncerResponsePeerImpl[ext_peers.length];
for (int i=0;i<ext_peers.length;i++){
DownloadAnnounceResultPeer ext_peer = ext_peers[i];
if (Logger.isEnabled())
Logger.log(new LogEvent(torrent, LOGID, "EXTERNAL PEER DHT: ip="
+ ext_peer.getAddress() + ",port=" + ext_peer.getPort() +",prot=" + ext_peer.getProtocol()));
int http_port = 0;
byte az_version = TRTrackerAnnouncer.AZ_TRACKER_VERSION_1;
peers[i] = new TRTrackerAnnouncerResponsePeerImpl(
ext_peer.getSource(),
ext_peer.getPeerID(),
ext_peer.getAddress(),
ext_peer.getPort(),
ext_peer.getUDPPort(),
http_port,
ext_peer.getProtocol(),
az_version,
(short)0 );
}
helper.addToTrackerCache( peers);
tracker_status_str = MessageText.getString("PeerManager.status.ok");
response = new TRTrackerAnnouncerResponseImpl( result.getURL(), torrent_hash, TRTrackerAnnouncerResponse.ST_ONLINE, result.getTimeToWait(), peers );
}
last_response = response;
TRTrackerAnnouncerResponsePeer[] peers = response.getPeers();
if ( peers == null || peers.length < 5 ){
TRTrackerAnnouncerResponsePeer[] cached_peers = helper.getPeersFromCache(100);
if ( cached_peers.length > 0 ){
Set<TRTrackerAnnouncerResponsePeer> new_peers =
new TreeSet<TRTrackerAnnouncerResponsePeer>(
new Comparator<TRTrackerAnnouncerResponsePeer>()
{
public int
compare(
TRTrackerAnnouncerResponsePeer o1,
TRTrackerAnnouncerResponsePeer o2 )
{
return( o1.compareTo( o2 ));
}
});
if ( peers != null ){
new_peers.addAll( Arrays.asList( peers ));
}
new_peers.addAll( Arrays.asList( cached_peers ));
response.setPeers( new_peers.toArray( new TRTrackerAnnouncerResponsePeer[new_peers.size()]) );
}
}
helper.informResponse( this, response );
}
public void
addListener(
TRTrackerAnnouncerListener l )
{
helper.addListener( l );
}
public void
removeListener(
TRTrackerAnnouncerListener l )
{
helper.removeListener( l );
}
public void
setTrackerResponseCache(
Map map )
{
helper.setTrackerResponseCache( map );
}
public void
removeFromTrackerResponseCache(
String ip, int tcpPort)
{
helper.removeFromTrackerResponseCache( ip, tcpPort );
}
public Map
getTrackerResponseCache()
{
return( helper.getTrackerResponseCache());
}
public TrackerPeerSource
getTrackerPeerSource(
TOTorrentAnnounceURLSet set)
{
Debug.out( "not implemented" );
return null;
}
public TrackerPeerSource
getCacheTrackerPeerSource()
{
Debug.out( "not implemented" );
return null;
}
public void
generateEvidence(
IndentWriter writer )
{
writer.println( "DHT announce: " + (last_response==null?"null":last_response.getString()));
}
}