/*
* File : TRTrackerServerPeerImpl.java
* Created : 5 Oct. 2003
* By : Parg
*
* Azureus - a Java Bittorrent client
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details ( see the LICENSE file ).
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.gudy.azureus2.core3.tracker.server.impl;
import java.net.*;
import java.util.*;
import org.gudy.azureus2.core3.util.*;
import org.gudy.azureus2.core3.tracker.server.*;
import com.aelitis.azureus.core.dht.netcoords.DHTNetworkPosition;
public class
TRTrackerServerPeerImpl
implements TRTrackerServerPeer, TRTrackerServerSimplePeer, HostNameToIPResolverListener, TRTrackerServerNatCheckerListener
{
private HashWrapper peer_id;
private int key_hash_code;
private byte[] ip;
private boolean ip_override;
private short tcp_port;
private short udp_port;
private short http_port;
private byte crypto_level;
private byte az_ver;
private String ip_str;
private byte[] ip_bytes;
private byte NAT_status = NAT_CHECK_UNKNOWN;
private long timeout;
private long uploaded;
private long downloaded;
private long amount_left;
private long last_contact_time;
private boolean download_completed;
private boolean biased;
private short up_speed;
// fields above are serialised when exported
private DHTNetworkPosition network_position;
private Object user_data;
protected
TRTrackerServerPeerImpl(
HashWrapper _peer_id,
int _key_hash_code,
byte[] _ip,
boolean _ip_override,
int _tcp_port,
int _udp_port,
int _http_port,
byte _crypto_level,
byte _az_ver,
long _last_contact_time,
boolean _download_completed,
byte _last_nat_status,
int _up_speed,
DHTNetworkPosition _network_position )
{
peer_id = _peer_id;
key_hash_code = _key_hash_code;
ip = _ip;
ip_override = _ip_override;
tcp_port = (short)_tcp_port;
udp_port = (short)_udp_port;
http_port = (short)_http_port;
crypto_level = _crypto_level;
az_ver = _az_ver;
last_contact_time = _last_contact_time;
download_completed = _download_completed;
NAT_status = _last_nat_status;
up_speed = _up_speed>Short.MAX_VALUE?Short.MAX_VALUE:(short)_up_speed;
network_position = _network_position;
resolveAndCheckNAT();
}
/**
* Import constructor
*/
protected
TRTrackerServerPeerImpl(
HashWrapper _peer_id,
int _key_hash_code,
byte[] _ip,
boolean _ip_override,
short _tcp_port,
short _udp_port,
short _http_port,
byte _crypto_level,
byte _az_ver,
String _ip_str,
byte[] _ip_bytes,
byte _NAT_status,
long _timeout,
long _uploaded,
long _downloaded,
long _amount_left,
long _last_contact_time,
boolean _download_completed,
boolean _biased,
short _up_speed )
{
peer_id = _peer_id;
key_hash_code = _key_hash_code;
ip = _ip;
ip_override = _ip_override;
tcp_port = _tcp_port;
udp_port = _udp_port;
http_port = _http_port;
crypto_level = _crypto_level;
az_ver = _az_ver;
ip_str = _ip_str;
ip_bytes = _ip_bytes;
NAT_status = _NAT_status;
timeout = _timeout;
uploaded = _uploaded;
downloaded = _downloaded;
amount_left = _amount_left;
last_contact_time = _last_contact_time;
download_completed = _download_completed;
biased = _biased;
up_speed = _up_speed;
}
protected boolean
update(
byte[] _ip,
int _port,
int _udp_port,
int _http_port,
byte _crypto_level,
byte _az_ver,
int _up_speed,
DHTNetworkPosition _network_position )
{
udp_port = (short)_udp_port;
http_port = (short)_http_port;
crypto_level = _crypto_level;
az_ver = _az_ver;
up_speed = _up_speed>Short.MAX_VALUE?Short.MAX_VALUE:(short)_up_speed;
network_position = _network_position;
boolean res = false;
if ( _port != getTCPPort() ){
tcp_port = (short)_port;
res = true;
}
if ( !Arrays.equals( _ip, ip )){
ip = _ip;
res = true;
}
if ( res ){
resolveAndCheckNAT();
}
return( res );
}
public void
NATCheckComplete(
boolean ok )
{
if ( ok ){
NAT_status = NAT_CHECK_OK;
}else{
NAT_status = NAT_CHECK_FAILED;
}
}
protected void
setNATStatus(
byte status )
{
NAT_status = status;
}
public byte
getNATStatus()
{
return( NAT_status );
}
protected boolean
isNATStatusBad()
{
return( NAT_status == NAT_CHECK_FAILED || NAT_status == NAT_CHECK_FAILED_AND_REPORTED );
}
protected void
resolveAndCheckNAT()
{
// default values pending resolution
ip_str = new String( ip );
ip_bytes = null;
HostNameToIPResolver.addResolverRequest( ip_str, this );
// a port of 0 is taken to mean that the client can't/won't receive incoming
// connections - tr
if ( tcp_port == 0 ){
NAT_status = NAT_CHECK_FAILED_AND_REPORTED;
}else{
// only recheck if we haven't already ascertained the state
if ( NAT_status == NAT_CHECK_UNKNOWN ){
NAT_status = NAT_CHECK_INITIATED;
if ( !TRTrackerServerNATChecker.getSingleton().addNATCheckRequest( ip_str, getTCPPort(), this )){
NAT_status = NAT_CHECK_DISABLED;
}
}
}
}
public void
hostNameResolutionComplete(
InetAddress address )
{
if ( address != null ){
ip_str = address.getHostAddress();
ip_bytes = address.getAddress();
}
}
protected long
getLastContactTime()
{
return( last_contact_time );
}
protected boolean
getDownloadCompleted()
{
return( download_completed );
}
protected void
setDownloadCompleted()
{
download_completed = true;
}
public boolean
isBiased()
{
return( biased );
}
public void
setBiased(
boolean _biased )
{
biased = _biased;
}
public HashWrapper
getPeerId()
{
return( peer_id );
}
public byte[]
getPeerID()
{
return( peer_id.getBytes());
}
protected int
getKeyHashCode()
{
return( key_hash_code );
}
public byte[]
getIPAsRead()
{
return( ip );
}
public String
getIPRaw()
{
return( new String(ip));
}
/**
* If asynchronous resolution of the address is required, this will return
* the non-resolved address until the async process completes
*/
public String
getIP()
{
return( ip_str );
}
protected boolean
isIPOverride()
{
return( ip_override );
}
/**
* This will return in resolution of the address is not complete or fails
* @return
*/
public byte[]
getIPAddressBytes()
{
return( ip_bytes );
}
public int
getTCPPort()
{
return( tcp_port&0xffff );
}
public int
getUDPPort()
{
return( udp_port&0xffff );
}
public int
getHTTPPort()
{
return( http_port&0xffff );
}
public byte
getCryptoLevel()
{
return( crypto_level );
}
public byte
getAZVer()
{
return( az_ver );
}
public int
getUpSpeed()
{
return( up_speed&0xffff );
}
public DHTNetworkPosition
getNetworkPosition()
{
return( network_position );
}
protected void
setTimeout(
long _now,
long _timeout )
{
last_contact_time = _now;
timeout = _timeout;
}
protected long
getTimeout()
{
return( timeout );
}
public int
getSecsToLive()
{
return((int)(( timeout - SystemTime.getCurrentTime())/1000 ));
}
protected void
setStats(
long _uploaded,
long _downloaded,
long _amount_left )
{
uploaded = _uploaded;
downloaded = _downloaded;
amount_left = _amount_left;
}
public long
getUploaded()
{
return( uploaded );
}
public long
getDownloaded()
{
return( downloaded );
}
public long
getAmountLeft()
{
return( amount_left );
}
public boolean
isSeed()
{
return( amount_left == 0 );
}
public void
setUserData(
Object key,
Object data )
{
if ( user_data == null ){
user_data = new Object[]{ key, data };
}else if ( user_data instanceof Object[]){
Object[] x = (Object[])user_data;
if ( x[0] == key ){
x[1] = data;
}else{
HashMap map = new HashMap();
user_data = map;
map.put( x[0], x[1] );
map.put( key, data );
}
}else{
((Map)user_data).put( key, data );
}
}
public Object
getUserData(
Object key )
{
if ( user_data == null ){
return( null );
}else if( user_data instanceof Object[]){
Object[] x = (Object[])user_data;
if ( x[0] == key ){
return( x[1] );
}else{
return( null );
}
}else{
return(((Map)user_data).get(key));
}
}
public Map
export()
{
Map map = new HashMap();
map.put( "peer_id", peer_id.getBytes());
map.put( "key_hash_code", new Long( key_hash_code ));
map.put( "ip", ip );
map.put( "ip_override", new Long( ip_override?1:0 ));
map.put( "tcp_port", new Long( tcp_port ));
map.put( "udp_port", new Long( udp_port ));
map.put( "http_port", new Long( http_port ));
map.put( "crypto_level", new Long( crypto_level ));
map.put( "az_ver", new Long( az_ver ));
map.put( "ip_str", ip_str );
if ( ip_bytes != null ){
map.put( "ip_bytes", ip_bytes );
}
map.put( "NAT_status", new Long( NAT_status ));
map.put( "timeout", new Long( timeout ));
map.put( "uploaded", new Long( uploaded ));
map.put( "downloaded", new Long( downloaded ));
map.put( "amount_left", new Long( amount_left ));
map.put( "last_contact_time", new Long( last_contact_time ));
map.put( "download_completed", new Long( download_completed?1:0 ));
map.put( "biased", new Long( biased?1:0 ));
map.put( "up_speed", new Long( up_speed ));
return( map );
}
public static TRTrackerServerPeerImpl
importPeer(
Map map )
{
try{
HashWrapper peer_id = new HashWrapper((byte[])map.get( "peer_id" ));
int key_hash_code = ((Long)map.get( "key_hash_code" )).intValue();
byte[] ip = (byte[])map.get( "ip" );
boolean ip_override = ((Long)map.get( "ip_override" )).intValue()==1;
short tcp_port = ((Long)map.get( "tcp_port" )).shortValue();
short udp_port = ((Long)map.get( "udp_port" )).shortValue();
short http_port = ((Long)map.get( "http_port" )).shortValue();
byte crypto_level = ((Long)map.get( "crypto_level" )).byteValue();
byte az_ver = ((Long)map.get( "az_ver" )).byteValue();
String ip_str = new String( (byte[])map.get( "ip_str" ));
byte[] ip_bytes = (byte[])map.get( "ip_bytes" );
byte NAT_status = ((Long)map.get( "NAT_status" )).byteValue();
long timeout = ((Long)map.get( "timeout" )).longValue();
long uploaded = ((Long)map.get( "uploaded" )).longValue();
long downloaded = ((Long)map.get( "downloaded" )).longValue();
long amount_left = ((Long)map.get( "amount_left" )).longValue();
long last_contact_time = ((Long)map.get( "last_contact_time" )).longValue();
boolean download_completed = ((Long)map.get( "download_completed" )).intValue() == 1;
boolean biased = ((Long)map.get( "biased" )).intValue() == 1;
short up_speed = ((Long)map.get( "up_speed" )).shortValue();
return(
new TRTrackerServerPeerImpl(
peer_id,
key_hash_code,
ip,
ip_override,
tcp_port,
udp_port,
http_port,
crypto_level,
az_ver,
ip_str,
ip_bytes,
NAT_status,
timeout,
uploaded,
downloaded,
amount_left,
last_contact_time,
download_completed,
biased,
up_speed ));
}catch( Throwable e ){
return( null );
}
}
protected String
getString()
{
return( new String(ip) + ":" + getTCPPort() + "(" + new String(peer_id.getHash()) + ")" );
}
}