📄 trtrackerserverprocessortcp.java
字号:
disable_timeouts = true;
// check non-tracker authentication
if ( !doAuthentication( url_path, input_header, os, false )){
return;
}
if ( handleExternalRequest( client_ip_address, str, input_header, is, os )){
return;
}
os.write( ("HTTP/1.1 404 Not Found\r\n\r\n").getBytes() );
os.flush();
return; // throw( new Exception( "Unsupported Request Type"));
}
// OK, here its an announce, scrape or full scrape
// check tracker authentication
if ( !doAuthentication( url_path, input_header, os, true )){
return;
}
int enc_pos = lowercase_input_header.indexOf( "accept-encoding:");
if ( enc_pos != -1 ){
int e_pos = input_header.indexOf( NL, enc_pos );
if ( e_pos != -1 ){
gzip_reply = input_header.substring(enc_pos+16,e_pos).toLowerCase().indexOf("gzip") != -1;
}
}
setTaskState( "decoding announce/scrape" );
int pos = 0;
String hash_str = null;
HashWrapper peer_id = null;
int port = 0;
String event = null;
long uploaded = 0;
long downloaded = 0;
long left = 0;
int num_want = -1;
boolean no_peer_id = false;
boolean compact = false;
String key = null;
while(pos < str.length()){
int p1 = str.indexOf( '&', pos );
String token;
if ( p1 == -1 ){
token = str.substring( pos );
}else{
token = str.substring( pos, p1 );
pos = p1+1;
}
int p2 = token.indexOf('=');
if ( p2 == -1 ){
throw( new Exception( "format invalid" ));
}
String lhs = token.substring( 0, p2 ).toLowerCase();
String rhs = URLDecoder.decode(token.substring( p2+1 ), Constants.BYTE_ENCODING );
// System.out.println( "param:" + lhs + " = " + rhs );
if ( lhs.equals( "info_hash" )){
hash_str = rhs;
}else if ( lhs.equals( "peer_id" )){
peer_id = new HashWrapper(rhs.getBytes(Constants.BYTE_ENCODING));
}else if ( lhs.equals( "no_peer_id" )){
no_peer_id = rhs.equals("1");
}else if ( lhs.equals( "compact" )){
if ( server.isCompactEnabled()){
compact = rhs.equals("1");
}
}else if ( lhs.equals( "key" )){
if ( server.isKeyEnabled()){
key = rhs;
}
}else if ( lhs.equals( "port" )){
port = Integer.parseInt( rhs );
}else if ( lhs.equals( "event" )){
event = rhs;
}else if ( lhs.equals( "ip" )){
client_ip_address = rhs;
}else if ( lhs.equals( "uploaded" )){
uploaded = Long.parseLong( rhs );
}else if ( lhs.equals( "downloaded" )){
downloaded = Long.parseLong( rhs );
}else if ( lhs.equals( "left" )){
left = Long.parseLong( rhs );
}else if ( lhs.equals( "numwant" )){
num_want = Integer.parseInt( rhs );
}
if ( p1 == -1 ){
break;
}
}
byte[] hash_bytes = null;
if ( hash_str != null ){
hash_bytes = hash_str.getBytes(Constants.BYTE_ENCODING);
}
Map[] root_out = new Map[1];
TRTrackerServerPeerImpl[] peer_out = new TRTrackerServerPeerImpl[1];
specific_torrent =
processTrackerRequest(
server, root_out, peer_out,
request_type,
hash_bytes,
peer_id, no_peer_id, compact, key,
event,
port,
client_ip_address,
downloaded, uploaded, left,
num_want );
root = root_out[0];
// only post-process if this isn't a cached entry
if ( root.get( "_data" ) == null ){
server.postProcess( peer_out[0], specific_torrent, request_type, root );
}
}catch( Exception e ){
String message = e.getMessage();
// e.printStackTrace();
if ( message == null || message.length() == 0 ){
// e.printStackTrace();
message = e.toString();
}
root = new HashMap();
root.put( "failure reason", message );
}
setTaskState( "writing response" );
// cache both plain and gzip encoded data for possible reuse
byte[] data = (byte[])root.get( "_data" );
if ( data == null ){
data = BEncoder.encode( root );
root.put( "_data", data );
}
if ( gzip_reply ){
byte[] gzip_data = (byte[])root.get( "_gzipdata");
if ( gzip_data == null ){
ByteArrayOutputStream tos = new ByteArrayOutputStream(data.length);
GZIPOutputStream gos = new GZIPOutputStream( tos );
gos.write( data );
gos.close();
gzip_data = tos.toByteArray();
root.put( "_gzipdata", gzip_data );
}
data = gzip_data;
}
// System.out.println( "TRTrackerServerProcessor::reply: sending " + new String(data));
// write the response
setTaskState( "writing header" );
os.write( HTTP_RESPONSE_START );
byte[] length_bytes = String.valueOf(data.length).getBytes();
os.write( length_bytes );
int header_len = HTTP_RESPONSE_START.length + length_bytes.length;
setTaskState( "writing content" );
if ( gzip_reply ){
os.write( HTTP_RESPONSE_END_GZIP );
header_len += HTTP_RESPONSE_END_GZIP.length;
}else{
os.write( HTTP_RESPONSE_END_NOGZIP );
header_len += HTTP_RESPONSE_END_NOGZIP.length;
}
os.write( data );
server.updateStats( specific_torrent, input_header.length(), header_len+data.length );
}finally{
setTaskState( "final os flush" );
os.flush();
}
}
protected boolean
doAuthentication(
String url_path,
String header,
OutputStream os,
boolean tracker )
throws IOException
{
// System.out.println( "doAuth: " + server.isTrackerPasswordEnabled() + "/" + server.isWebPasswordEnabled());
boolean apply_web_password = (!tracker) && server.isWebPasswordEnabled();
boolean apply_torrent_password = tracker && server.isTrackerPasswordEnabled();
if ( apply_web_password &&
server.isWebPasswordHTTPSOnly() &&
!server.isSSL()){
os.write( ("HTTP/1.1 403 BAD\r\n\r\nAccess Denied\r\n").getBytes() );
os.flush();
return( false );
}else if ( apply_torrent_password ||
apply_web_password ){
int x = header.indexOf( "Authorization:" );
if ( x == -1 ){
// auth missing. however, if we have external auth defined
// and external auth is happy with junk then allow it through
if ( server.hasExternalAuthorisation()){
try{
String resource_str =
( server.isSSL()?"https":"http" ) + "://" +
server.getHost() + ":" + server.getPort() + url_path;
URL resource = new URL( resource_str );
if ( server.performExternalAuthorisation( resource, "", "" )){
return( true );
}
}catch( MalformedURLException e ){
Debug.printStackTrace( e );
}
}
}else{
// Authorization: Basic dG9tY2F0OnRvbWNhdA==
int p1 = header.indexOf(' ', x );
int p2 = header.indexOf(' ', p1+1 );
String body = header.substring( p2, header.indexOf( '\r', p2 )).trim();
String decoded=new String(new BASE64Decoder().decodeBuffer(body));
// username:password
int cp = decoded.indexOf(':');
String user = decoded.substring(0,cp);
String pw = decoded.substring(cp+1);
boolean auth_failed = false;
if ( server.hasExternalAuthorisation()){
try{
String resource_str =
( server.isSSL()?"https":"http" ) + "://" +
server.getHost() + ":" + server.getPort() + url_path;
URL resource = new URL( resource_str );
if ( server.performExternalAuthorisation( resource, user, pw )){
return( true );
}
}catch( MalformedURLException e ){
Debug.printStackTrace( e );
}
auth_failed = true;
}
if ( server.hasInternalAuthorisation() && !auth_failed ){
try{
SHA1Hasher hasher = new SHA1Hasher();
byte[] password = pw.getBytes();
byte[] encoded;
if( password.length > 0){
encoded = hasher.calculateHash(password);
}else{
encoded = new byte[0];
}
if ( user.equals( "<internal>")){
byte[] internal_pw = new BASE64Decoder().decodeBuffer(pw);
if ( Arrays.equals( internal_pw, server.getPassword())){
return( true );
}
}else if ( user.equalsIgnoreCase(server.getUsername()) &&
Arrays.equals(encoded, server.getPassword())){
return( true );
}
}catch( Exception e ){
Debug.printStackTrace( e );
}
}
}
os.write( ("HTTP/1.1 401 BAD\r\nWWW-Authenticate: Basic realm=\"" + server.getName() + "\"\r\n\r\nAccess Denied\r\n").getBytes() );
os.flush();
return( false );
}else{
return( true );
}
}
protected boolean
handleExternalRequest(
String client_address,
String url,
String header,
InputStream is,
OutputStream os )
throws IOException
{
return( server.handleExternalRequest(client_address,url,header, is, os));
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -