📄 dhttrackerplugin.java
字号:
if (( value.getFlags() & DHTPlugin.FLAG_DOWNLOADING ) == 1 ){
leecher_count++;
}else{
seed_count++;
}
}catch( Throwable e ){
// in case we get crap back (someone spamming the DHT) just
// silently ignore
}
}
public void
valueWritten(
DHTPluginContact target,
DHTPluginValue value )
{
}
public void
complete(
boolean timeout_occurred )
{
log.log(dl.getTorrent(), LoggerChannel.LT_INFORMATION,
"Get of '" + dl.getName() + "' completed (elapsed="
+ (SystemTime.getCurrentTime() - start)
+ "), addresses = " + addresses.size() + ", seeds = "
+ seed_count + ", leechers = " + leecher_count);
decreaseActive(dl);
final DownloadAnnounceResultPeer[] peers = new
DownloadAnnounceResultPeer[addresses.size()];
// scale min and max based on number of active torrents
// we don't want more than a few announces a minute
int announce_per_min = 4;
int num_active = query_map.size();
int announce_min = Math.max( ANNOUNCE_MIN_DEFAULT, ( num_active / announce_per_min )*60*1000 );
announce_min = Math.min( announce_min, ANNOUNCE_MAX );
final long retry = announce_min + peers.length*(ANNOUNCE_MAX-announce_min)/NUM_WANT;
try{
this_mon.enter();
if ( running_downloads.contains( dl )){
query_map.put( dl, new Long( SystemTime.getCurrentTime() + retry ));
}
}finally{
this_mon.exit();
}
for (int i=0;i<peers.length;i++){
final int f_i = i;
peers[i] =
new DownloadAnnounceResultPeer()
{
public String
getSource()
{
return( PEPeerSource.PS_DHT );
}
public String
getAddress()
{
return((String)addresses.get(f_i));
}
public int
getPort()
{
return(((Integer)ports.get(f_i)).intValue());
}
public byte[]
getPeerID()
{
return( null );
}
public short
getProtocol()
{
String flag = (String)flags.get(f_i);
short protocol;
if ( flag != null && flag.indexOf("C") != -1 ){
protocol = PROTOCOL_CRYPT;
}else{
protocol = PROTOCOL_NORMAL;
}
return( protocol );
}
};
}
if ( dl.getState() == Download.ST_DOWNLOADING ||
dl.getState() == Download.ST_SEEDING ){
dl.setAnnounceResult(
new DownloadAnnounceResult()
{
public Download
getDownload()
{
return( dl );
}
public int
getResponseType()
{
return( DownloadAnnounceResult.RT_SUCCESS );
}
public int
getReportedPeerCount()
{
return( peers.length);
}
public int
getSeedCount()
{
return( seed_count );
}
public int
getNonSeedCount()
{
return( leecher_count );
}
public String
getError()
{
return( null );
}
public URL
getURL()
{
return( url_to_report );
}
public DownloadAnnounceResultPeer[]
getPeers()
{
return( peers );
}
public long
getTimeToWait()
{
return( retry/1000 );
}
public Map
getExtensions()
{
return( null );
}
});
}
// only inject the scrape result if the torrent is decentralised. If we do this for
// "normal" torrents then it can have unwanted side-effects, such as stopping the torrent
// due to ignore rules if there are no downloaders in the DHT - bthub backup, for example,
// isn't scrapable...
// hmm, ok, try being a bit more relaxed about this, inject the scrape if
// we have any peers.
boolean inject_scrape = leecher_count > 0;
DownloadScrapeResult result = dl.getLastScrapeResult();
if ( result == null ||
result.getResponseType() == DownloadScrapeResult.RT_ERROR ){
}else{
// if the currently reported values are the same as the
// ones we previously injected then overwrite them
// note that we can't test the URL to see if we originated
// the scrape values as this gets replaced when a normal
// scrape fails :(
int[] prev = (int[])scrape_injection_map.get( dl );
if ( prev != null &&
prev[0] == result.getSeedCount() &&
prev[1] == result.getNonSeedCount()){
inject_scrape = true;
}
}
if ( torrent.isDecentralised() || inject_scrape ){
// make sure that the injected scrape values are consistent
// with our currently connected peers
PeerManager pm = dl.getPeerManager();
int local_seeds = 0;
int local_leechers = 0;
if ( pm != null ){
Peer[] dl_peers = pm.getPeers();
for (int i=0;i<dl_peers.length;i++){
Peer dl_peer = dl_peers[i];
if ( dl_peer.getPercentDoneInThousandNotation() == 1000 ){
local_seeds++;
}else{
local_leechers++;
}
}
}
final int f_adj_seeds = Math.max( seed_count, local_seeds );
final int f_adj_leechers = Math.max( leecher_count, local_leechers );
scrape_injection_map.put( dl, new int[]{ f_adj_seeds, f_adj_leechers });
dl.setScrapeResult(
new DownloadScrapeResult()
{
public Download
getDownload()
{
return( dl );
}
public int
getResponseType()
{
return( RT_SUCCESS );
}
public int
getSeedCount()
{
return( f_adj_seeds );
}
public int
getNonSeedCount()
{
return( f_adj_leechers );
}
public long
getScrapeStartTime()
{
return( start );
}
public void
setNextScrapeStartTime(
long nextScrapeStartTime)
{
}
public long
getNextScrapeStartTime()
{
return( SystemTime.getCurrentTime() + retry );
}
public String
getStatus()
{
return( "OK" );
}
public URL
getURL()
{
return( url_to_report );
}
});
}
}
});
}
}
}
}
public void
stateChanged(
Download download,
int old_state,
int new_state )
{
int state = download.getState();
try{
this_mon.enter();
if ( state == Download.ST_DOWNLOADING ||
state == Download.ST_SEEDING ||
state == Download.ST_QUEUED ){ // included queued here for the mo to avoid lots
// of thrash for torrents that flip a lot
if ( running_downloads.contains( download )){
// force requery
query_map.put( download, new Long( SystemTime.getCurrentTime()));
}
}
}finally{
this_mon.exit();
}
checkDownloadForRegistration( download, false );
}
public void
positionChanged(
Download download,
int oldPosition,
int newPosition )
{
}
protected void
configChanged()
{
Download[] downloads = plugin_interface.getDownloadManager().getDownloads();
for (int i=0;i<downloads.length;i++){
checkDownloadForRegistration(downloads[i], false );
}
}
public DownloadScrapeResult
scrape(
byte[] hash )
{
final int[] seeds = {0};
final int[] leechers = {0};
final AESemaphore sem = new AESemaphore( "DHTTrackerPlugin:scrape" );
dht.get(hash,
"Scrape for '" + ByteFormatter.nicePrint( hash ) + "'",
DHTPlugin.FLAG_DOWNLOADING,
NUM_WANT,
SCRAPE_TIMEOUT,
false,
new DHTPluginOperationListener()
{
public void
valueRead(
DHTPluginContact originator,
DHTPluginValue value )
{
if (( value.getFlags() & DHTPlugin.FLAG_DOWNLOADING ) == 1 ){
leechers[0]++;
}else{
seeds[0]++;
}
}
public void
valueWritten(
DHTPluginContact target,
DHTPluginValue value )
{
}
public void
complete(
boolean timeout_occurred )
{
sem.release();
}
});
sem.reserve();
return(
new DownloadScrapeResult()
{
public Download
getDownload()
{
return( null );
}
public int
getResponseType()
{
return( RT_SUCCESS );
}
public int
getSeedCount()
{
return( seeds[0] );
}
public int
getNonSeedCount()
{
return( leechers[0] );
}
public long
getScrapeStartTime()
{
return( 0 );
}
public void
setNextScrapeStartTime(
long nextScrapeStartTime)
{
}
public long
getNextScrapeStartTime()
{
return( 0 );
}
public String
getStatus()
{
return( "OK" );
}
public URL
getURL()
{
return( null );
}
});
}
protected void
increaseActive(
Download dl )
{
try{
this_mon.enter();
Integer active_i = (Integer)in_progress.get( dl );
int active = active_i==null?0:active_i.intValue();
in_progress.put( dl, new Integer( active+1 ));
}finally{
this_mon.exit();
}
}
protected void
decreaseActive(
Download dl )
{
try{
this_mon.enter();
Integer active_i = (Integer)in_progress.get( dl );
if ( active_i == null ){
Debug.out( "active count inconsistent" );
}else{
int active = active_i.intValue()-1;
if ( active == 0 ){
in_progress.remove( dl );
}else{
in_progress.put( dl, new Integer( active ));
}
}
}finally{
this_mon.exit();
}
}
protected boolean
isActive(
Download dl )
{
try{
this_mon.enter();
return( in_progress.get(dl) != null );
}finally{
this_mon.exit();
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -