📄 trtrackerbtannouncerimpl.java
字号:
list.add(url);
trackerUrlLists.add(list);
}else{
//Ok we have a multi-tracker torrent
for(int i = 0 ; i < announce_sets.length ; i++){
//Each list contains a list of urls
URL[] urls = announce_sets[i].getAnnounceURLs();
List random_urls = new ArrayList();
for(int j = 0 ; j < urls.length; j++){
//System.out.println(urls.get(j).getClass());
URL url = urls[j];
//Shuffle
int pos = shuffle?(int)(Math.random() * (random_urls.size()+1)):j;
random_urls.add(pos,url);
}
//Add this list to the list
trackerUrlLists.add(random_urls);
}
}
}catch(Exception e){
Debug.printStackTrace( e );
}
}
protected String
trackerURLListToString()
{
String trackerUrlListString = "[";
for (int i=0;i<trackerUrlLists.size();i++){
List group = (List)trackerUrlLists.get(i);
trackerUrlListString += (i==0?"":",") + "[";
for (int j=0;j<group.size();j++){
URL u = (URL)group.get(j);
trackerUrlListString += (j==0?"":",") + u.toString();
}
trackerUrlListString += "]";
}
trackerUrlListString += "]";
return( trackerUrlListString );
}
protected TRTrackerAnnouncerResponseImpl
decodeTrackerResponse(
URL url,
byte[] data )
{
String failure_reason;
if ( data == null ){
failure_reason = "no response";
}else{
try{
//parse the metadata
try{
Map metaData = BDecoder.decode(data); //$NON-NLS-1$
// handle any user warnings in the response
try{
byte[] b_warning_message = (byte[])metaData.get( "warning message" );
if ( b_warning_message != null &&
COConfigurationManager.getBooleanParameter( "Tracker Client Show Warnings" )){
String warning_message = new String(b_warning_message);
// don't report the same message twice per torrent
if ( !warning_message.equals( last_tracker_message )){
last_tracker_message = warning_message;
boolean log_it = false;
// only report a given message once per tracker
try{
class_mon.enter();
String last_warning_message = (String)tracker_report_map.get( url.getHost());
if ( last_warning_message == null ||
!warning_message.equals( last_warning_message )){
log_it = true;
tracker_report_map.put( url.getHost(), warning_message );
}
}finally{
class_mon.exit();
}
if ( log_it ){
Logger.logTextResource(new LogAlert(LogAlert.UNREPEATABLE,
LogAlert.AT_WARNING,
"TrackerClient.announce.warningmessage"), new String[] {
announce_data_provider.getName(), warning_message });
}
}
}
}catch( Throwable e ){
Debug.printStackTrace( e );
}
long time_to_wait;
try {
time_to_wait = ((Long) metaData.get("interval")).longValue();
Long raw_min_interval = (Long) metaData.get("min interval");
if (Logger.isEnabled()) {
Logger.log(new LogEvent(torrent, LOGID, LogEvent.LT_INFORMATION,
"Received from announce: 'interval' = " + time_to_wait
+ "; 'min interval' = " + raw_min_interval));
}
// guard against crazy return values
if (time_to_wait < 0 || time_to_wait > 0xffffffffL) {
time_to_wait = 0xffffffffL;
}
if (raw_min_interval != null) {
min_interval = raw_min_interval.longValue();
// ignore useless values
// Note: Many trackers set min_interval and interval the same.
if (min_interval < 1) {
if (Logger.isEnabled()) {
Logger.log(new LogEvent(
torrent,
LOGID,
LogEvent.LT_INFORMATION,
"Tracker being silly and "
+ "returning a 'min interval' of less than 1 second ("
+ min_interval + ")"));
}
min_interval = 0;
} else if (min_interval > time_to_wait) {
if (Logger.isEnabled()) {
Logger.log(new LogEvent(
torrent,
LOGID,
LogEvent.LT_INFORMATION,
"Tracker being silly and "
+ "returning a 'min interval' ("
+ min_interval
+ ") greater than recommended announce 'interval'"
+ " (" + time_to_wait + ")"));
}
min_interval = 0;
}
}
// roll back 10 seconds to make sure we announce before the tracker
// times us out. This is done after min_interval in order not to
// mess up the "ignore useless values"
if (time_to_wait > 30)
time_to_wait -= 10;
} catch (Exception e) {
byte[] failure_reason_bytes = (byte[]) metaData.get("failure reason");
if ( failure_reason_bytes == null ){
if (Logger.isEnabled())
Logger.log(new LogEvent(torrent, LOGID, LogEvent.LT_WARNING,
"Problems with Tracker, will retry in "
+ getErrorRetryInterval() + "ms"));
return( new TRTrackerAnnouncerResponseImpl( url, torrent_hash, TRTrackerAnnouncerResponse.ST_OFFLINE, getErrorRetryInterval(), "Unknown cause" ));
}
// explicit failure from the tracker
failure_reason = new String( failure_reason_bytes, Constants.DEFAULT_ENCODING);
return( new TRTrackerAnnouncerResponseImpl( url, torrent_hash, TRTrackerAnnouncerResponse.ST_REPORTED_ERROR, getErrorRetryInterval(), failure_reason ));
}
//System.out.println("Response from Announce: " + new String(data));
Long incomplete_l = (Long)metaData.get("incomplete");
Long complete_l = (Long)metaData.get("complete");
if ( incomplete_l != null || complete_l != null ){
if (Logger.isEnabled())
Logger.log(new LogEvent(torrent, LOGID,
"ANNOUNCE SCRAPE1: seeds=" + complete_l + " peers="
+ incomplete_l));
}
//TrackerID extension, used by phpbt trackers.
//We reply with '&trackerid=1234' when we receive
//'10:tracker id4:1234e' on announce reply.
//NOTE: we receive as 'tracker id' but reply as 'trackerid'
byte[] trackerid = (byte[])metaData.get( "tracker id" );
if( trackerid != null ) {
tracker_id = new String( trackerid );
}
byte[] crypto_flags = (byte[])metaData.get( "crypto_flags" );
//build the list of peers
List valid_meta_peers = new ArrayList();
Object meta_peers_peek = metaData.get( "peers" );
Long az_compact_l = (Long)metaData.get( "azcompact" );
long az_compact = az_compact_l==null?0:az_compact_l.longValue();
boolean this_is_az_tracker = az_compact == 2;
if ( az_tracker != this_is_az_tracker || lastUsedUrl != lastAZTrackerCheckedURL ){
lastAZTrackerCheckedURL = lastUsedUrl;
az_tracker = this_is_az_tracker;
TRTrackerUtils.setAZTracker( url, az_tracker );
}
if ( az_compact == 2 ){
// latest return to dictionary based data
List meta_peers = (List)meta_peers_peek;
int peers_length = meta_peers.size();
if ( peers_length > 1 ){
// calculate average rtt to use for those with no rtt
long total_rtt = 0;
int rtt_count = 0;
for ( int i = 0; i < peers_length; i++ ){
Map peer = (Map) meta_peers.get(i);
Long l_rtt = (Long)peer.get( "r" );
if ( l_rtt != null ){
total_rtt += l_rtt.longValue();
rtt_count++;
}
}
final int average_rtt = (int)( rtt_count==0?0:(total_rtt/rtt_count));
// sort into smallest rtt order with biased at front
Collections.sort(
meta_peers,
new Comparator()
{
public int
compare(
Object o1,
Object o2 )
{
Map map1 = (Map)o1;
Map map2 = (Map)o2;
Long l_rtt1 = (Long)map1.get( "r" );
Long l_rtt2 = (Long)map2.get( "r" );
boolean biased_1 = map1.containsKey( "b" );
boolean biased_2 = map2.containsKey( "b" );
if ( biased_1 == biased_2 ){
int rtt1 = l_rtt1==null?average_rtt:l_rtt1.intValue();
int rtt2 = l_rtt2==null?average_rtt:l_rtt2.intValue();
return( rtt1 - rtt2 );
}else if ( biased_1 ){
return( -1 );
}else{
return( +1 );
}
}
});
// interleave non-biased peers with good rtt
int biased_pos = peers_length;
int non_biased_pos = peers_length;
for ( int i = 0; i < peers_length; i++ ){
Map peer = (Map) meta_peers.get(i);
if ( peer.containsKey( "b" )){
if ( i == 0 ){
biased_pos = i;
}
}else{
non_biased_pos = i;
break;
}
}
List new_peers = new ArrayList(peers_length);
int non_biased_start = non_biased_pos;
boolean last_biased = true;
while( biased_pos < non_biased_start || non_biased_pos < peers_length ){
if ( biased_pos < non_biased_start ){
if ( non_biased_pos < peers_length ){
Map biased = (Map) meta_peers.get(biased_pos);
Map non_biased = (Map) meta_peers.get(non_biased_pos);
boolean use_biased;
if ( !last_biased ){
use_biased = true;
}else{
Long l_rtt_biased = (Long)biased.get( "r" );
Long l_rtt_non_biased = (Long)non_biased.get( "r" );
int biased_rtt = l_rtt_biased==null?average_rtt:l_rtt_biased.intValue();
int non_biased_rtt = l_rtt_non_biased==null?average_rtt:l_rtt_non_biased.intValue();
use_biased = non_biased_rtt >= biased_rtt;
}
if ( use_biased ){
new_peers.add( biased );
biased_pos++;
}else{
new_peers.add( non_biased );
non_biased_pos++;
}
last_biased = use_biased;
}else{
new_peers.add( meta_peers.get( biased_pos++ ));
}
}else{
new_peers.add( meta_peers.get( non_biased_pos++ ));
}
}
meta_peers = new_peers;
}
for ( int i = 0; i < peers_length; i++ ){
Map peer = (Map) meta_peers.get(i);
try{
byte[] ip_bytes = (byte[])peer.get("i");
int ip1 = 0xff & ip_bytes[0];
int ip2 = 0xff & ip_bytes[1];
int ip3 = 0xff & ip_bytes[2];
int ip4 = 0xff & ip_bytes[3];
String ip = ip1 + "." + ip2 + "." + ip3 + "." + ip4;
byte[] tcp_bytes = (byte[])peer.get("t");
int tcp_port = ((tcp_bytes[0]&0xff) << 8 ) + (tcp_bytes[1]&0xff );
byte[] peer_peer_id = getAnonymousPeerId( ip, tcp_port );
int udp_port = 0;
byte[] udp_bytes = (byte[])peer.get("u");
if ( udp_bytes != null ){
if ( udp_bytes.length == 0 ){
udp_port = tcp_port;
}else{
udp_port = ((udp_bytes[0]&0xff) << 8 ) + (udp_bytes[1]&0xff );
}
}
int http_port = 0;
byte[] http_bytes = (byte[])peer.get("h");
if ( http_bytes != null ){
http_port = ((http_bytes[0]&0xff) << 8 ) + (http_bytes[1]&0xff );
}
short protocol = DownloadAnnounceResultPeer.PROTOCOL_NORMAL;
byte[] protocol_bytes = (byte[])peer.get("c");
if ( protocol_bytes != null ){
protocol = (protocol_bytes[0]&0x01)==0?DownloadAnnounceResultPeer.PROTOCOL_NORMAL:DownloadAnnounceResultPeer.PROTOCOL_CRYPT;
}
Long l_azver = (Long)peer.get("v" );
byte az_ver = l_azver==null?TRTrackerAnnouncer.AZ_TRACKER_VERSION_1:l_azver.byteValue();
Long l_up_speed = (Long)peer.get( "s" );
TRTrackerAnnouncerResponsePeerImpl new_peer =
new TRTrackerAnnouncerResponsePeerImpl(
PEPeerSource.PS_BT_TRACKER,
peer_peer_id,
ip,
tcp_port,
udp_port,
http_port,
protocol,
az_ver,
l_up_speed==null?0:l_up_speed.shortValue());
if (Logger.isEnabled()){
String extra = "";
Long l_rtt = (Long)peer.get( "r" );
if ( l_rtt != null ){
extra = ",rtt=" + l_rtt;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -