📄 trhostimpl.java
字号:
urlRefresh()
{
}
};
tracker_client.addListener(listener);
tracker_client.refreshListeners();
}
protected void
remove(
TRHostTorrent host_torrent )
{
try{
this_mon.enter();
if ( !host_torrents.contains( host_torrent )){
return;
}
host_torrents.remove( host_torrent );
TOTorrent torrent = host_torrent.getTorrent();
try{
host_torrent_hash_map.remove(new HashWrapper(torrent.getHash()));
}catch( TOTorrentException e ){
Debug.printStackTrace( e );
}
host_torrent_map.remove( torrent );
if ( host_torrent instanceof TRHostTorrentHostImpl ){
stopHosting((TRHostTorrentHostImpl)host_torrent );
}
listeners.dispatch( LDT_TORRENT_REMOVED, host_torrent );
// this'll get saved sometime soon anyway - performance problems
// here when removing multiple torrents from a large set (e.g. 1000)
// config.saveConfig();
}finally{
this_mon.exit();
}
}
protected void
stopHosting(
TRHostTorrentHostImpl host_torrent )
{
TOTorrent torrent = host_torrent.getTorrent();
TRTrackerAnnouncer tc = (TRTrackerAnnouncer)tracker_client_map.get( torrent );
if ( tc != null ){
stopHosting( host_torrent, tc );
}
}
protected void
stopHosting(
TRTrackerAnnouncer tracker_client )
{
TRHostTorrent host_torrent = (TRHostTorrent)host_torrent_map.get( tracker_client.getTorrent());
if ( host_torrent instanceof TRHostTorrentHostImpl ){
// we only "connect" the announcer and the hosted torrent if it isn't passive. This allows
// us to make a torrent passive without losing the tracker stats by
// 1) making it passive
// 2) removing the Download
//if ( !host_torrent.isPassive()){
stopHosting( (TRHostTorrentHostImpl)host_torrent, tracker_client );
//}
}
}
protected void
stopHosting(
final TRHostTorrentHostImpl host_torrent,
final TRTrackerAnnouncer tracker_client )
{
// unfortunately a lot of the "stop" operations that occur when a tracker client
// connection is closed happen async. In particular the "stopped" message to the
// tracker. Hence, if we switch the URL back here the "stopped" doesn't get
// through.
// for the moment stick a delay in to allow any async stuff to complete
Thread thread = new AEThread("StopHosting")
{
public void
runSupport()
{
try{
Thread.sleep(2500);
}catch( InterruptedException e ){
}
try{
this_mon.enter();
// got to look up the host torrent again as may have been
// removed and re-added
TRHostTorrent ht = lookupHostTorrent( host_torrent.getTorrent());
// check it's still in stopped state and hasn't been restarted
if ( ht == null ||
( ht == host_torrent &&
ht.getStatus() == TRHostTorrent.TS_STOPPED )){
tracker_client.clearIPOverride();
}
}finally{
this_mon.exit();
}
}
};
thread.setDaemon(true);
thread.start();
}
protected TRTrackerAnnouncer
getTrackerClient(
TRHostTorrent host_torrent )
{
try{
this_mon.enter();
return((TRTrackerAnnouncer)tracker_client_map.get( host_torrent.getTorrent()));
}finally{
this_mon.exit();
}
}
protected void
hostTorrentStateChange(
TRHostTorrent host_torrent )
{
try{
this_mon.enter();
TOTorrent torrent = host_torrent.getTorrent();
TRTrackerAnnouncer tc = (TRTrackerAnnouncer)tracker_client_map.get( torrent );
if ( tc != null ){
tc.refreshListeners();
}
// config will get saved soon anyway (periodic or on closedown) - perf issues
// here with multiple torrent removal if we save each time
// config.saveConfig();
}finally{
this_mon.exit();
}
}
public TRHostTorrent[]
getTorrents()
{
try{
this_mon.enter();
TRHostTorrent[] res = new TRHostTorrent[host_torrents.size()];
host_torrents.toArray( res );
return( res );
}finally{
this_mon.exit();
}
}
public void
clientCreated(
TRTrackerAnnouncer client )
{
try{
this_mon.enter();
tracker_client_map.put( client.getTorrent(), client );
startHosting( client );
}finally{
this_mon.exit();
}
}
public void
clientDestroyed(
TRTrackerAnnouncer client )
{
try{
this_mon.enter();
tracker_client_map.remove( client.getTorrent());
stopHosting( client );
}finally{
this_mon.exit();
}
}
protected TRHostTorrent
lookupHostTorrentViaHash(
byte[] hash )
{
return((TRHostTorrent)host_torrent_hash_map.get(new HashWrapper(hash)));
}
// reports from TRTrackerServer regarding state of hashes
// if we get a "permitted" event for a torrent we know nothing about
// the the server is allowing public hosting and this is a new hash
// create an 'external' entry for it
public boolean
permitted(
byte[] hash,
boolean explicit )
{
try{
this_mon.enter();
TRHostTorrent ht = lookupHostTorrentViaHash( hash );
if ( ht != null ){
if ( !explicit ){
if ( ht.getStatus() != TRHostTorrent.TS_STARTED ){
return( false );
}
}
return( true );
}
addExternalTorrent( hash, TRHostTorrent.TS_STARTED, SystemTime.getCurrentTime());
return( true );
}finally{
this_mon.exit();
}
}
protected void
addExternalTorrent(
byte[] hash,
int state,
long date_added )
{
try{
this_mon.enter();
if ( lookupHostTorrentViaHash( hash ) != null ){
return;
}
String tracker_ip = COConfigurationManager.getStringParameter("Tracker IP", "127.0.0.1");
// external torrents don't care whether ssl or not so just assume non-ssl for simplicity
int port = COConfigurationManager.getIntParameter("Tracker Port", TRHost.DEFAULT_PORT );
try{
TOTorrent external_torrent = new TRHostExternalTorrent(hash, new URL( "http://" + tracker_ip + ":" + port + "/announce"));
addTorrent( external_torrent, state, true, false, date_added );
}catch( Throwable e ){
Debug.printStackTrace( e );
}
}finally{
this_mon.exit();
}
}
public boolean
denied(
byte[] hash,
boolean permitted )
{
return( true );
}
public boolean
handleExternalRequest(
InetSocketAddress client_address,
String user,
String url,
URL absolute_url,
String header,
InputStream is,
OutputStream os )
throws IOException
{
List listeners_copy = listeners.getListenersCopy();
for (int i=0;i<listeners_copy.size();i++){
TRHostListener listener = (TRHostListener)listeners_copy.get(i);
if ( listener.handleExternalRequest( client_address, user, url, absolute_url, header, is, os )){
return( true );
}
}
return( false );
}
public TRHostTorrent
getHostTorrent(
TOTorrent torrent )
{
return( lookupHostTorrent( torrent ));
}
public void
addListener(
TRHostListener l )
{
try{
this_mon.enter();
listeners.addListener( l );
for (int i=0;i<host_torrents.size();i++){
listeners.dispatch( l, LDT_TORRENT_ADDED, host_torrents.get(i));
}
}finally{
this_mon.exit();
}
}
public void
removeListener(
TRHostListener l )
{
listeners.removeListener( l );
}
protected void
torrentListenerRegistered()
{
try{
this_mon.enter();
if ( !server_factory_listener_added ){
server_factory_listener_added = true;
TRTrackerServerFactory.addListener( this );
}
}finally{
this_mon.exit();
}
}
public void
serverCreated(
TRTrackerServer server )
{
server.addRequestListener(this);
}
public void
preProcess(
TRTrackerServerRequest request )
throws TRTrackerServerException
{
if ( request.getType() == TRTrackerServerRequest.RT_ANNOUNCE ||
request.getType() == TRTrackerServerRequest.RT_SCRAPE ){
TRTrackerServerTorrent ts_torrent = request.getTorrent();
HashWrapper hash_wrapper = ts_torrent.getHash();
TRHostTorrent h_torrent = lookupHostTorrentViaHash( hash_wrapper.getHash());
if ( h_torrent != null ){
TRHostTorrentRequest req = new TRHostTorrentRequestImpl( h_torrent, new TRHostPeerHostImpl(request.getPeer()), request );
try{
if ( h_torrent instanceof TRHostTorrentHostImpl ){
((TRHostTorrentHostImpl)h_torrent).preProcess( req );
}else{
((TRHostTorrentPublishImpl)h_torrent).preProcess( req );
}
}catch( TRHostException e ){
throw( new TRTrackerServerException( e.getMessage(), e ));
}catch( Throwable e ){
throw( new TRTrackerServerException( "Pre-process fails", e ));
}
}
}
}
public void
postProcess(
TRTrackerServerRequest request )
throws TRTrackerServerException
{
if ( request.getType() == TRTrackerServerRequest.RT_ANNOUNCE ||
request.getType() == TRTrackerServerRequest.RT_SCRAPE ){
TRTrackerServerTorrent ts_torrent = request.getTorrent();
// can be null for multi-hash scrapes... should fix this sometime I guess
if ( ts_torrent != null ){
HashWrapper hash_wrapper = ts_torrent.getHash();
TRHostTorrent h_torrent = lookupHostTorrentViaHash( hash_wrapper.getHash());
if ( h_torrent != null ){
TRHostTorrentRequest req = new TRHostTorrentRequestImpl( h_torrent, new TRHostPeerHostImpl(request.getPeer()), request );
try{
if ( h_torrent instanceof TRHostTorrentHostImpl ){
((TRHostTorrentHostImpl)h_torrent).postProcess( req );
}else{
((TRHostTorrentPublishImpl)h_torrent).postProcess( req );
}
}catch( TRHostException e ){
throw( new TRTrackerServerException( "Post process fails", e ));
}
}
}
}
}
public void
close()
{
closed = true;
config.saveConfig( true );
}
public boolean
authenticate(
URL resource,
String user,
String password )
{
for (int i=0;i<auth_listeners.size();i++){
try{
boolean res = ((TRHostAuthenticationListener)auth_listeners.get(i)).authenticate( resource, user, password );
if ( res ){
return(true );
}
}catch( Throwable e ){
Debug.printStackTrace( e );
}
}
return( false );
}
public byte[]
authenticate(
URL resource,
String user )
{
for (int i=0;i<auth_listeners.size();i++){
try{
byte[] res = ((TRHostAuthenticationListener)auth_listeners.get(i)).authenticate( resource, user );
if ( res != null ){
return( res );
}
}catch( Throwable e ){
Debug.printStackTrace( e );
}
}
return( null );
}
public void
addAuthenticationListener(
TRHostAuthenticationListener l )
{
try{
this_mon.enter();
auth_listeners.add(l);
if ( auth_listeners.size() == 1 ){
Iterator it = server_map.values().iterator();
while( it.hasNext()){
((TRTrackerServer)it.next()).addAuthenticationListener( this );
}
}
}finally{
this_mon.exit();
}
}
public void
removeAuthenticationListener(
TRHostAuthenticationListener l )
{
try{
this_mon.enter();
auth_listeners.remove(l);
if ( auth_listeners.size() == 0 ){
Iterator it = server_map.values().iterator();
while( it.hasNext()){
((TRTrackerServer)it.next()).removeAuthenticationListener( this );
}
}
}finally{
this_mon.exit();
}
}
// see comment in TRHostTorrentHost impl for reason for this delegation + monitor
// aquisition
protected void
startTorrent(
TRHostTorrentHostImpl torrent )
{
try{
this_mon.enter();
torrent.startSupport();
}finally{
this_mon.exit();
}
}
protected void
stopTorrent(
TRHostTorrentHostImpl torrent )
{
try{
this_mon.enter();
torrent.stopSupport();
}finally{
this_mon.exit();
}
}
protected void
addTrackerAnnounce(
TOTorrent torrent )
{
if ( TorrentUtils.isDecentralised( torrent )){
return;
}
// ensure that the tracker's announce details are in the torrent
URL[][] url_sets = TRTrackerUtils.getAnnounceURLs();
if ( url_sets.length == 0 ){
// fall back to decentralised, no tracker defined
TorrentUtils.setDecentralised( torrent );
}else{
URL[] primary_urls = url_sets[0];
// backwards so that they end up in right order
for (int i=primary_urls.length-1;i>=0;i--){
String url_str = primary_urls[i].toString();
if ( TorrentUtils.announceGroupsContainsURL( torrent, url_str )){
TorrentUtils.announceGroupsSetFirst( torrent, url_str );
}else{
TorrentUtils.announceGroupsInsertFirst( torrent, url_str );
}
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -