📄 dhttrackerplugin.java
字号:
this_mon.enter();
query_map.remove( dl );
}finally{
this_mon.exit();
}
increaseActive( dl );
dht.remove(
dl.getTorrent().getHash(),
"Tracker deregistration of '" + dl.getName() + "'",
new DHTPluginOperationListener()
{
public void
diversified()
{
}
public void
valueRead(
DHTPluginContact originator,
DHTPluginValue value )
{
}
public void
valueWritten(
DHTPluginContact target,
DHTPluginValue value )
{
}
public void
complete(
boolean timeout_occurred )
{
log.log(dl.getTorrent(), LoggerChannel.LT_INFORMATION,
"Unregistration of '" + dl.getName() + "' completed (elapsed="
+ (SystemTime.getCurrentTime() - start) + ")");
decreaseActive( dl );
}
});
}
}
it = rds.iterator();
while( it.hasNext()){
final Download dl = (Download)it.next();
Long next_time;
try{
this_mon.enter();
next_time = (Long)query_map.get( dl );
}finally{
this_mon.exit();
}
if ( next_time != null && now >= next_time.longValue()){
try{
this_mon.enter();
query_map.remove( dl );
}finally{
this_mon.exit();
}
final long start = SystemTime.getCurrentTime();
// if we're already connected to > NUM_WANT peers then don't bother announcing
PeerManager pm = dl.getPeerManager();
// don't query if this download already has an active DHT operation
boolean skip = isActive( dl );
if ( skip ){
log.log(dl.getTorrent(), LoggerChannel.LT_INFORMATION,
"Deferring announce for '" + dl.getName()
+ "' as activity outstanding");
}
if ( pm != null && !skip ){
int con = pm.getStats().getConnectedLeechers() + pm.getStats().getConnectedSeeds();
skip = con >= NUM_WANT;
}
if ( skip ){
try{
this_mon.enter();
if ( running_downloads.contains( dl )){
// use "min" here as we're just deferring it
query_map.put( dl, new Long( start + ANNOUNCE_MIN_DEFAULT ));
}
}finally{
this_mon.exit();
}
}else{
final Torrent torrent = dl.getTorrent();
final URL url_to_report = torrent.isDecentralised()?torrent.getAnnounceURL():DEFAULT_URL;
increaseActive( dl );
dht.get(dl.getTorrent().getHash(),
"Tracker announce for '" + dl.getName() + "'",
dl.isComplete()?DHTPlugin.FLAG_SEEDING:DHTPlugin.FLAG_DOWNLOADING,
NUM_WANT,
ANNOUNCE_TIMEOUT,
false, false,
new DHTPluginOperationListener()
{
List addresses = new ArrayList();
List ports = new ArrayList();
List udp_ports = new ArrayList();
List is_seeds = new ArrayList();
List flags = new ArrayList();
int seed_count;
int leecher_count;
public void
diversified()
{
}
public void
valueRead(
DHTPluginContact originator,
DHTPluginValue value )
{
try{
String[] tokens = new String(value.getValue()).split(";");
String tcp_part = tokens[0].trim();
int sep = tcp_part.indexOf(':');
String ip_str = null;
String tcp_port_str;
if ( sep == -1 ){
tcp_port_str = tcp_part;
}else{
ip_str = tcp_part.substring( 0, sep );
tcp_port_str = tcp_part.substring( sep+1 );
}
int tcp_port = Integer.parseInt( tcp_port_str );
if ( tcp_port > 0 && tcp_port < 65536 ){
String flag_str = null;
int udp_port = -1;
try{
for (int i=1;i<tokens.length;i++){
String token = tokens[i].trim();
if ( token.length() > 0 ){
if ( Character.isDigit( token.charAt( 0 ))){
udp_port = Integer.parseInt( token );
if ( udp_port <= 0 || udp_port >=65536 ){
udp_port = -1;
}
}else{
flag_str = token;
}
}
}
}catch( Throwable e ){
}
addresses.add(
ip_str==null?originator.getAddress().getAddress().getHostAddress():ip_str);
ports.add( new Integer( tcp_port ));
udp_ports.add( new Integer( udp_port==-1?originator.getAddress().getPort():udp_port));
flags.add( flag_str );
if (( value.getFlags() & DHTPlugin.FLAG_DOWNLOADING ) == 1 ){
leecher_count++;
is_seeds.add( new Boolean( false ));
}else{
is_seeds.add( new Boolean( true ));
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);
int peers_found = addresses.size();
List peers_for_announce = new ArrayList();
// 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_found*(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();
}
boolean we_are_seeding = dl.getState() == Download.ST_SEEDING;
for (int i=0;i<addresses.size();i++){
// when we are seeding ignore seeds
if ( we_are_seeding && ((Boolean)is_seeds.get(i)).booleanValue()){
continue;
}
final int f_i = i;
peers_for_announce.add(
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 int
getUDPPort()
{
return(((Integer)udp_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 ){
final DownloadAnnounceResultPeer[] peers = new DownloadAnnounceResultPeer[peers_for_announce.size()];
peers_for_announce.toArray( peers );
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 );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -