📄 trtrackerserverprocessorudp.java
字号:
/*
* File : TRTrackerServerProcessorUDP.java
* Created : 20-Jan-2004
* 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.udp;
/**
* @author parg
*
*/
import java.net.*;
import java.io.*;
import java.security.SecureRandom;
import java.util.*;
import org.gudy.azureus2.core3.util.*;
import org.gudy.azureus2.core3.logging.*;
import org.gudy.azureus2.core3.tracker.server.*;
import org.gudy.azureus2.core3.tracker.server.impl.*;
import org.gudy.azureus2.core3.tracker.protocol.*;
import org.gudy.azureus2.core3.tracker.protocol.udp.*;
import com.aelitis.net.udp.uc.PRUDPPacket;
import com.aelitis.net.udp.uc.PRUDPPacketRequest;
public class
TRTrackerServerProcessorUDP
extends TRTrackerServerProcessor
{
private static final LogIDs LOGID = LogIDs.TRACKER;
// client may connect + then retry announce up to 4 times -> * 6
public static final long CONNECTION_ID_LIFETIME = PRUDPPacket.DEFAULT_UDP_TIMEOUT*6;
private TRTrackerServerUDP server;
private DatagramSocket socket;
private DatagramPacket request_dg;
private static Map connection_id_map = new LinkedHashMap();
private static SecureRandom random = new SecureRandom();
private static AEMonitor random_mon = new AEMonitor( "TRTrackerServerUDP:rand" );
static{
PRUDPTrackerCodecs.registerCodecs();
}
protected
TRTrackerServerProcessorUDP(
TRTrackerServerUDP _server,
DatagramSocket _socket,
DatagramPacket _packet )
{
server = _server;
socket = _socket;
request_dg = _packet;
}
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;
}
}
}
}
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];
}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];
}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 );
if ( torrent != null ){
server.updateStats( 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 ){
}
}
}
public void
interruptTask()
{
}
protected long
allocateConnectionId(
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(
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{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -