📄 trtrackerbtannouncerimpl.java
字号:
}finally{
this_mon.exit();
}
}
public int
getLastUpdateTime()
{
return( (int)last_update_time_secs );
}
public void
update(
boolean force )
{
long now = SystemTime.getCurrentTime() / 1000;
if ( now < last_update_time_secs ) force = true; //time went backwards
long effective_min = min_interval_override>0?min_interval_override:REFRESH_MINIMUM_SECS;
if ( manual_control || force || ( now - last_update_time_secs >= effective_min )){
requestUpdate();
}
}
public void
complete(
boolean already_reported )
{
complete_reported = (complete_reported || already_reported );
completed = true;
requestUpdate();
}
public void
stop(
boolean for_queue )
{
stopped = true;
stopped_for_queue = for_queue;
requestUpdate();
}
protected void
requestUpdate()
{
try{
this_mon.enter();
if ( current_timer_event != null ){
current_timer_event.cancel();
}
rd_last_override = SystemTime.getCurrentTime(); //"pause" overrides for 10s
if ( !destroyed ){
if (Logger.isEnabled())
Logger.log(new LogEvent(torrent, LOGID,
"Forcing tracker announce now via "
+ Debug.getStackTrace(true, false, 0, 3)));
current_timer_event =
tracker_timer.addEvent(
SystemTime.getCurrentTime(),
timer_event_action );
}
}finally{
this_mon.exit();
}
}
protected long
requestUpdateSupport()
{
boolean clear_progress = true;
try{
try{
this_mon.enter();
// can't continue if the data provider hasn't been set yet...
if ( update_in_progress || announce_data_provider == null ){
clear_progress = false;
return( getErrorRetryInterval() );
}
update_in_progress = true;
}finally{
this_mon.exit();
}
last_update_time_secs = SystemTime.getCurrentTime()/1000;
tracker_status_str = MessageText.getString("PeerManager.status.checking") + "..."; //$NON-NLS-1$ //$NON-NLS-2$
TRTrackerAnnouncerResponse response = null;
if ( stopped ){
if ( tracker_state == TS_INITIALISED ){
// never started
tracker_state = TS_STOPPED;
}else if ( tracker_state != TS_STOPPED ){
response = stopSupport();
if ( response.getStatus() == TRTrackerAnnouncerResponse.ST_ONLINE ){
tracker_state = TS_STOPPED;
}else{
// just have one go at sending a stop event as we don't want to sit here
// forever trying to send stop to a stuffed tracker
tracker_state = TS_STOPPED;
}
}
}else if ( tracker_state == TS_INITIALISED ){
// always go through the "start" phase, even if we're already complete
// as some trackers insist on the initial "start"
response = startSupport();
if ( response.getStatus() == TRTrackerAnnouncerResponse.ST_ONLINE ){
tracker_state = TS_DOWNLOADING;
}
}else if ( completed ){
if ( !complete_reported ){
response = completeSupport();
// treat the "complete" as processed if the tracker replies either OK or an explicit
// error. In particular, if the tracker has returned an error to control seed limits
// we don't want to treat this as an error and report completed again next time around
// as this causes the tracker to double count stats
if ( response.getStatus() != TRTrackerAnnouncerResponse.ST_OFFLINE ){
complete_reported = true;
tracker_state = TS_COMPLETED;
}
}else{
tracker_state = TS_COMPLETED;
response = updateSupport();
}
}else{
response = updateSupport();
}
if ( response != null ){
int rs = response.getStatus();
if ( rs == TRTrackerAnnouncerResponse.ST_OFFLINE ){
tracker_status_str = MessageText.getString("PeerManager.status.offline");
}else if ( rs == TRTrackerAnnouncerResponse.ST_REPORTED_ERROR ){
tracker_status_str = MessageText.getString("PeerManager.status.error");
// move state back to initialised to next time around a "started"
// event it resent. Required for trackers like 123torrents.com that
// will fail peers that don't start with a "started" event after a
// tracker restart
tracker_state = TS_INITIALISED;
}else{
tracker_status_str = MessageText.getString("PeerManager.status.ok"); //set the status //$NON-NLS-1$
}
String reason = response.getAdditionalInfo();
if ( reason != null ){
tracker_status_str += " (" + reason + ")";
}
last_response = response;
listeners.dispatch( LDT_TRACKER_RESPONSE, response );
return( response.getTimeToWait());
}
tracker_status_str = "";
return( getErrorRetryInterval() );
}catch( Throwable e ){
Debug.printStackTrace( e );
return( getErrorRetryInterval() );
}finally{
try{
this_mon.enter();
if ( clear_progress ){
update_in_progress = false;
}
}finally{
this_mon.exit();
}
}
}
protected TRTrackerAnnouncerResponse startSupport() {
if (Logger.isEnabled())
Logger.log(new LogEvent(torrent, LOGID, "Tracker Announcer is sending "
+ "a start Request"));
return (update("started"));
}
protected TRTrackerAnnouncerResponse completeSupport() {
if (Logger.isEnabled())
Logger.log(new LogEvent(torrent, LOGID, "Tracker Announcer is sending "
+ "a completed Request"));
return (update("completed"));
}
protected TRTrackerAnnouncerResponse stopSupport() {
if (Logger.isEnabled())
Logger.log(new LogEvent(torrent, LOGID, "Tracker Announcer is sending "
+ "a stopped Request"));
return (update("stopped"));
}
protected TRTrackerAnnouncerResponse updateSupport() {
if (Logger.isEnabled())
Logger.log(new LogEvent(torrent, LOGID, "Tracker Announcer is sending "
+ "an update Request"));
return update("");
}
private TRTrackerAnnouncerResponse
update(
String evt )
{
// this method filters out any responses incompatible with the network selection
TRTrackerAnnouncerResponseImpl resp = update2( evt );
TRTrackerAnnouncerResponsePeer[] peers = resp.getPeers();
if ( peers != null ){
List p = new ArrayList();
for (int i=0;i<peers.length;i++){
TRTrackerAnnouncerResponsePeer peer = peers[i];
if ( peer_networks == null ){
p.add( peer );
}else{
String peer_address = peer.getAddress();
String peer_network = AENetworkClassifier.categoriseAddress( peer_address );
boolean added = false;
for (int j=0;j<peer_networks.length;j++){
if ( peer_networks[j] == peer_network ){
p.add( peer );
added = true;
break;
}
}
if (!added && Logger.isEnabled())
Logger.log(new LogEvent(torrent, LOGID, LogEvent.LT_WARNING,
"Tracker Announcer dropped peer '" + peer_address
+ "' as incompatible " + "with network selection"));
}
}
peers = new TRTrackerAnnouncerResponsePeer[ p.size()];
p.toArray( peers );
resp.setPeers( peers );
}
return( resp );
}
private TRTrackerAnnouncerResponseImpl
update2(String evt)
{
TRTrackerAnnouncerResponseImpl last_failure_resp = null;
String skip_host = null;
outer:
for (int i = 0 ; i < trackerUrlLists.size() ; i++) {
List urls = (List) trackerUrlLists.get(i);
for (int j = 0 ; j < urls.size() ; j++) {
URL original_url = (URL)urls.get(j);
if ( skip_host != null && skip_host.equals( original_url.getHost())){
if (Logger.isEnabled())
Logger.log(
new LogEvent(
torrent,
LOGID,
LogEvent.LT_WARNING,
"Tracker Announcer is ignoring '" + original_url + "' as already received overloaded response from this host" ));
continue;
}
lastUsedUrl = original_url;
if ( lastUsedUrl != lastAZTrackerCheckedURL ){
az_tracker = TRTrackerUtils.isAZTracker( lastUsedUrl );
}
URL request_url = null;
try{
request_url = constructUrl(evt,original_url);
URL[] tracker_url = { original_url };
byte[] result_bytes = updateOld( tracker_url, request_url);
lastUsedUrl = tracker_url[0]; // url may have redirected, use this value as it will be correct
TRTrackerAnnouncerResponseImpl resp = decodeTrackerResponse( lastUsedUrl, result_bytes );
int resp_status = resp.getStatus();
if ( resp_status == TRTrackerAnnouncerResponse.ST_ONLINE ){
try{
// tracker looks ok, make any redirection permanent
if ( !original_url.toString().equals(lastUsedUrl.toString())){
if (Logger.isEnabled())
Logger.log(new LogEvent(torrent, LOGID,
"announce url permanently redirected: old = " + original_url + ", new = " + lastUsedUrl ));
TorrentUtils.replaceAnnounceURL( torrent, original_url, lastUsedUrl );
}
}catch( Throwable e ){
Debug.printStackTrace(e);
}
urls.remove(j);
urls.add(0, lastUsedUrl );
trackerUrlLists.remove(i);
trackerUrlLists.add(0,urls);
informURLChange( lastUsedUrl, false );
//and return the result
return( resp );
}else if ( resp_status == TRTrackerAnnouncerResponse.ST_REPORTED_ERROR ){
last_failure_resp = resp;
String reason = resp.getAdditionalInfo();
// avoid re-hitting a host with multiple ports if reporting overloaded. This is
// particularly "interesting" when reporting the "completed" event and we get a
// "overloaded" response - when we hit another port we record the event twice
// as the tracker has discarded this peer and therefore doesn't know to ignore the
// second "completed" event...
if ( reason != null &&
( reason.indexOf( "too many seeds" ) != -1 ||
reason.indexOf( "too many peers" ) != -1 )){
skip_host = original_url.getHost();
}
}else{
last_failure_resp = resp;
}
}catch( MalformedURLException e ){
Debug.printStackTrace( e );
last_failure_resp =
new TRTrackerAnnouncerResponseImpl(
original_url,
torrent_hash,
TRTrackerAnnouncerResponse.ST_OFFLINE,
getErrorRetryInterval(),
"malformed URL '" + (request_url==null?"<null>":request_url.toString()) + "'" );
}catch( Exception e ){
last_failure_resp =
new TRTrackerAnnouncerResponseImpl(
original_url,
torrent_hash,
TRTrackerAnnouncerResponse.ST_OFFLINE,
getErrorRetryInterval(),
e.getMessage()==null?e.toString():e.getMessage());
}
if ( destroyed ){
break outer;
}
}
}
// things no good here
if ( last_failure_resp == null ){
last_failure_resp =
new TRTrackerAnnouncerResponseImpl(
null,
torrent_hash,
TRTrackerAnnouncerResponse.ST_OFFLINE,
getErrorRetryInterval(),
"Reason Unknown" );
}
// use 4* the num_want as no doubt a fair few connections will fail and
// we want to get a decent reconnect rate
int num_want = calculateNumWant() * 4;
TRTrackerAnnouncerResponsePeer[] cached_peers = getPeersFromCache(num_want);
if ( cached_peers.length > 0 ){
// System.out.println( "cached peers used:" + cached_peers.length );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -