TRTrackerServerProcessorUDPpublic class TRTrackerServerProcessorUDP extends TRTrackerServerProcessor
Fields Summary |
---|
private static final LogIDs | LOGID | public static final long | CONNECTION_ID_LIFETIME | private TRTrackerServerUDP | server | private DatagramSocket | socket | private DatagramPacket | request_dg | private static Map | connection_id_map | private static SecureRandom | random | private static AEMonitor | random_mon |
Methods Summary |
---|
protected long | allocateConnectionId(java.lang.String client_address)
try{
random_mon.enter();
long id = random.nextLong();
Long new_key = new Long(id);
connectionData new_data = new connectionData( client_address );
// check for timeouts
Iterator it = connection_id_map.keySet().iterator();
while(it.hasNext()){
Long key = (Long)it.next();
connectionData data = (connectionData)connection_id_map.get(key);
if ( new_data.getTime() - data.getTime() > CONNECTION_ID_LIFETIME ){
// System.out.println( "TRTrackerServerProcessorUDP: conection id timeout" );
it.remove();
}else{
// insertion order into map is time based - LinkedHashMap returns keys in same order
break;
}
}
connection_id_map.put( new_key, new_data );
// System.out.println( "TRTrackerServerProcessorUDP: allocated:" + id + ", conection id map size = " + connection_id_map.size());
return( id );
}finally{
random_mon.exit();
}
| protected boolean | checkConnectionId(java.lang.String client_address, long id)
try{
random_mon.enter();
Long key = new Long(id);
connectionData data = (connectionData)connection_id_map.get( key );
if ( data == null ){
// System.out.println( "TRTrackerServerProcessorUDP: rejected:" + id + ", data not found" );
return( false );
}else{
// single shot id, can't be reused
connection_id_map.remove( key );
}
boolean ok = data.getAddress().equals( client_address );
// System.out.println( "TRTrackerServerProcessorUDP: tested:" + id + "/" + client_address + " -> " + ok );
return( ok );
}finally{
random_mon.exit();
}
| protected java.lang.Object[] | handleAnnounceAndScrape(java.lang.String client_ip_address, com.aelitis.net.udp.uc.PRUDPPacketRequest request, int request_type)
if ( !checkConnectionId( client_ip_address, request.getConnectionId())){
return( null );
}
byte[] hash_bytes = null;
HashWrapper peer_id = null;
int port = 0;
String event = null;
long uploaded = 0;
long downloaded = 0;
long left = 0;
int num_want = -1;
String key = null;
if ( request_type == TRTrackerServerRequest.RT_ANNOUNCE ){
if ( PRUDPPacketTracker.VERSION == 1 ){
PRUDPPacketRequestAnnounce announce = (PRUDPPacketRequestAnnounce)request;
hash_bytes = announce.getHash();
peer_id = new HashWrapper( announce.getPeerId());
port = announce.getPort();
int i_event = announce.getEvent();
switch( i_event ){
case PRUDPPacketRequestAnnounce.EV_STARTED:
{
event = "started";
break;
}
case PRUDPPacketRequestAnnounce.EV_STOPPED:
{
event = "stopped";
break;
}
case PRUDPPacketRequestAnnounce.EV_COMPLETED:
{
event = "completed";
break;
}
}
uploaded = announce.getUploaded();
downloaded = announce.getDownloaded();
left = announce.getLeft();
num_want = announce.getNumWant();
int i_ip = announce.getIPAddress();
if ( i_ip != 0 ){
client_ip_address = PRHelpers.intToAddress( i_ip );
}
}else{
PRUDPPacketRequestAnnounce2 announce = (PRUDPPacketRequestAnnounce2)request;
hash_bytes = announce.getHash();
peer_id = new HashWrapper( announce.getPeerId());
port = announce.getPort();
int i_event = announce.getEvent();
switch( i_event ){
case PRUDPPacketRequestAnnounce.EV_STARTED:
{
event = "started";
break;
}
case PRUDPPacketRequestAnnounce.EV_STOPPED:
{
event = "stopped";
break;
}
case PRUDPPacketRequestAnnounce.EV_COMPLETED:
{
event = "completed";
break;
}
}
uploaded = announce.getUploaded();
downloaded = announce.getDownloaded();
left = announce.getLeft();
num_want = announce.getNumWant();
int i_ip = announce.getIPAddress();
if ( i_ip != 0 ){
client_ip_address = PRHelpers.intToAddress( i_ip );
}
key = "" + announce.getKey();
}
}else{
PRUDPPacketRequestScrape scrape = (PRUDPPacketRequestScrape)request;
hash_bytes = scrape.getHash();
}
Map[] root_out = new Map[1];
TRTrackerServerPeerImpl[] peer_out = new TRTrackerServerPeerImpl[1];
TRTrackerServerTorrentImpl torrent =
processTrackerRequest(
server, "", root_out, peer_out,
request_type,
new byte[][]{ hash_bytes }, null, null,
peer_id, false, TRTrackerServerTorrentImpl.COMPACT_MODE_NONE, key, // currently no "no_peer_id" / "compact" in the packet and anyway they aren't returned / key
event, false,
port,
0, 0,
client_ip_address, client_ip_address,
downloaded, uploaded, left,
num_want,
TRTrackerServerPeer.CRYPTO_NONE,
(byte)1,
0,
null );
Map root = root_out[0];
if ( request_type == TRTrackerServerRequest.RT_ANNOUNCE ){
if ( PRUDPPacketTracker.VERSION == 1 ){
PRUDPPacketReplyAnnounce reply = new PRUDPPacketReplyAnnounce(request.getTransactionId());
reply.setInterval(((Long)root.get("interval")).intValue());
List peers = (List)root.get("peers");
int[] addresses = new int[peers.size()];
short[] ports = new short[addresses.length];
for (int i=0;i<addresses.length;i++){
Map peer = (Map)peers.get(i);
addresses[i] = PRHelpers.addressToInt(new String((byte[])peer.get("ip")));
ports[i] = (short)((Long)peer.get("port")).shortValue();
}
reply.setPeers( addresses, ports );
return( new Object[]{ reply, torrent });
}else{
PRUDPPacketReplyAnnounce2 reply = new PRUDPPacketReplyAnnounce2(request.getTransactionId());
reply.setInterval(((Long)root.get("interval")).intValue());
boolean local_scrape = client_ip_address.equals( "127.0.0.1" );
Map scrape_details = torrent.exportScrapeToMap( "", client_ip_address,!local_scrape );
int seeders = ((Long)scrape_details.get("complete")).intValue();
int leechers = ((Long)scrape_details.get("incomplete")).intValue();
reply.setLeechersSeeders(leechers,seeders);
List peers = (List)root.get("peers");
int[] addresses = new int[peers.size()];
short[] ports = new short[addresses.length];
for (int i=0;i<addresses.length;i++){
Map peer = (Map)peers.get(i);
addresses[i] = PRHelpers.addressToInt(new String((byte[])peer.get("ip")));
ports[i] = (short)((Long)peer.get("port")).shortValue();
}
reply.setPeers( addresses, ports );
return( new Object[]{ reply, torrent });
}
}else{
if ( PRUDPPacketTracker.VERSION == 1 ){
PRUDPPacketReplyScrape reply = new PRUDPPacketReplyScrape(request.getTransactionId());
/*
Long interval = (Long)root.get("interval");
if ( interval != null ){
reply.setInterval(interval.intValue());
}
*/
Map files = (Map)root.get( "files" );
byte[][] hashes = new byte[files.size()][];
int[] s_complete = new int[hashes.length];
int[] s_downloaded = new int[hashes.length];
int[] s_incomplete = new int[hashes.length];
Iterator it = files.keySet().iterator();
int pos = 0;
while(it.hasNext()){
String hash_str = (String)it.next();
hashes[pos] = hash_str.getBytes( Constants.BYTE_ENCODING );
Map details = (Map)files.get( hash_str );
s_complete[pos] = ((Long)details.get("complete")).intValue();
s_incomplete[pos] = ((Long)details.get("incomplete")).intValue();
s_downloaded[pos] = ((Long)details.get("downloaded")).intValue();
pos++;
}
reply.setDetails( hashes, s_complete, s_downloaded, s_incomplete );
return( new Object[]{ reply, torrent });
}else{
PRUDPPacketReplyScrape2 reply = new PRUDPPacketReplyScrape2(request.getTransactionId());
/*
Long interval = (Long)root.get("interval");
if ( interval != null ){
reply.setInterval(interval.intValue());
}
*/
Map files = (Map)root.get( "files" );
int[] s_complete = new int[files.size()];
int[] s_downloaded = new int[s_complete.length];
int[] s_incomplete = new int[s_complete.length];
Iterator it = files.keySet().iterator();
int pos = 0;
while(it.hasNext()){
String hash_str = (String)it.next();
Map details = (Map)files.get( hash_str );
s_complete[pos] = ((Long)details.get("complete")).intValue();
s_incomplete[pos] = ((Long)details.get("incomplete")).intValue();
s_downloaded[pos] = ((Long)details.get("downloaded")).intValue();
pos++;
}
reply.setDetails( s_complete, s_downloaded, s_incomplete );
return( new Object[]{ reply, torrent });
}
}
| protected com.aelitis.net.udp.uc.PRUDPPacket | handleConnect(java.lang.String client_ip_address, com.aelitis.net.udp.uc.PRUDPPacketRequest request)
long conn_id = allocateConnectionId( client_ip_address );
PRUDPPacket reply = new PRUDPPacketReplyConnect(request.getTransactionId(), conn_id );
return( reply );
| public void | interruptTask()
| public void | runSupport()
byte[] input_buffer = new byte[request_dg.getLength()];
System.arraycopy( request_dg.getData(), 0, input_buffer, 0, input_buffer.length );
int packet_data_length = input_buffer.length;
String auth_user = null;
byte[] auth_user_bytes = null;
byte[] auth_hash = null;
if ( server.isTrackerPasswordEnabled()){
// auth detail should be attached to the packet. Auth details are 16
// bytes
if ( input_buffer.length < 17 ){
Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING,
"TRTrackerServerProcessorUDP: "
+ "packet received but authorisation missing"));
return;
}
packet_data_length -= 16;
auth_user_bytes = new byte[8];
auth_hash = new byte[8];
System.arraycopy( input_buffer, packet_data_length, auth_user_bytes, 0, 8 );
int user_len = 0;
while( user_len < 8 && auth_user_bytes[user_len] != 0 ){
user_len++;
}
auth_user = new String( auth_user_bytes, 0, user_len );
System.arraycopy( input_buffer, packet_data_length+8, auth_hash, 0, 8 );
}
DataInputStream is = new DataInputStream(new ByteArrayInputStream(input_buffer, 0, packet_data_length ));
try{
String client_ip_address = request_dg.getAddress().getHostAddress();
PRUDPPacketRequest request = PRUDPPacketRequest.deserialiseRequest( null, is );
Logger.log(new LogEvent(LOGID,
"TRTrackerServerProcessorUDP: packet received: "
+ request.getString()));
PRUDPPacket reply = null;
TRTrackerServerTorrentImpl torrent = null;
if ( auth_user_bytes != null ){
// user name is irrelevant as we only have one at the moment
//<parg_home> so <new_packet> = <old_packet> + <user_padded_to_8_bytes> + <hash>
//<parg_home> where <hash> = first 8 bytes of sha1(<old_packet> + <user_padded_to_8> + sha1(pass))
//<XTF> Yes
byte[] sha1_pw = null;
if ( server.hasExternalAuthorisation()){
try{
URL resource = new URL( "udp://" + server.getHost() + ":" + server.getPort() + "/" );
sha1_pw = server.performExternalAuthorisation( resource, auth_user );
}catch( MalformedURLException e ){
Debug.printStackTrace( e );
}
if ( sha1_pw == null ){
Logger.log(new LogEvent(LOGID, LogEvent.LT_ERROR,
"TRTrackerServerProcessorUDP: auth fails for user '"
+ auth_user + "'"));
reply = new PRUDPPacketReplyError( request.getTransactionId(), "Access Denied" );
}
}else{
sha1_pw = server.getPassword();
}
// if we haven't already failed then check the PW
if ( reply == null ){
SHA1Hasher hasher = new SHA1Hasher();
hasher.update( input_buffer, 0, packet_data_length);
hasher.update( auth_user_bytes );
hasher.update( sha1_pw );
byte[] digest = hasher.getDigest();
for (int i=0;i<auth_hash.length;i++){
if ( auth_hash[i] != digest[i] ){
Logger.log(new LogEvent(LOGID, LogEvent.LT_ERROR,
"TRTrackerServerProcessorUDP: auth fails for user '"
+ auth_user + "'"));
reply = new PRUDPPacketReplyError( request.getTransactionId(), "Access Denied" );
break;
}
}
}
}
int request_type = TRTrackerServerRequest.RT_UNKNOWN;
if( reply == null ){
try{
int type = request.getAction();
if ( type == PRUDPPacketTracker.ACT_REQUEST_CONNECT ){
reply = handleConnect( client_ip_address, request );
}else if (type == PRUDPPacketTracker.ACT_REQUEST_ANNOUNCE ){
Object[] x = handleAnnounceAndScrape( client_ip_address, request, TRTrackerServerRequest.RT_ANNOUNCE );
reply = (PRUDPPacket)x[0];
torrent = (TRTrackerServerTorrentImpl)x[1];
request_type = TRTrackerServerRequest.RT_ANNOUNCE;
}else if ( type == PRUDPPacketTracker.ACT_REQUEST_SCRAPE ){
Object[] x = handleAnnounceAndScrape( client_ip_address, request, TRTrackerServerRequest.RT_SCRAPE );
reply = (PRUDPPacket)x[0];
torrent = (TRTrackerServerTorrentImpl)x[1];
request_type = TRTrackerServerRequest.RT_SCRAPE;
}else{
reply = new PRUDPPacketReplyError( request.getTransactionId(), "unsupported action");
}
}catch( Throwable e ){
// e.printStackTrace();
String error = e.getMessage();
if ( error == null ){
error = e.toString();
}
reply = new PRUDPPacketReplyError( request.getTransactionId(), error );
}
}
if ( reply != null ){
InetAddress address = request_dg.getAddress();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream os = new DataOutputStream( baos );
reply.serialise(os);
byte[] output_buffer = baos.toByteArray();
DatagramPacket reply_packet = new DatagramPacket(output_buffer, output_buffer.length,address,request_dg.getPort());
socket.send( reply_packet );
server.updateStats( request_type, torrent, input_buffer.length, output_buffer.length );
}
}catch( Throwable e ){
Logger.log(new LogEvent(LOGID,
"TRTrackerServerProcessorUDP: processing fails", e));
}finally{
try{
is.close();
}catch( Throwable e ){
}
}
|
|