/*
* File : TRTrackerServerImpl.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.tcp;
import java.net.*;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;
import org.gudy.azureus2.core3.util.*;
import org.gudy.azureus2.core3.config.*;
import org.gudy.azureus2.core3.tracker.server.*;
import org.gudy.azureus2.core3.tracker.server.impl.*;
public abstract class
TRTrackerServerTCP
extends TRTrackerServerImpl
{
private static int THREAD_POOL_SIZE = COConfigurationManager.getIntParameter( "Tracker Max Threads" );
public static long PROCESSING_GET_LIMIT = COConfigurationManager.getIntParameter( "Tracker Max GET Time" )*1000;
public static int PROCESSING_POST_MULTIPLIER = COConfigurationManager.getIntParameter( "Tracker Max POST Time Multiplier" );
static{
// sanity checks
if ( THREAD_POOL_SIZE <= 0 ){
THREAD_POOL_SIZE = 1;
}
if ( PROCESSING_GET_LIMIT < 0 ){
PROCESSING_GET_LIMIT = 0;
}
if ( PROCESSING_POST_MULTIPLIER < 0 ){
PROCESSING_POST_MULTIPLIER = 0;
}
}
private boolean ssl;
private int port;
private boolean apply_ip_filter;
private ThreadPool thread_pool;
public
TRTrackerServerTCP(
String _name,
int _port,
boolean _ssl,
boolean _apply_ip_filter,
boolean _start_up_ready )
throws TRTrackerServerException
{
super( _name, _start_up_ready );
port = _port;
ssl = _ssl;
apply_ip_filter = _apply_ip_filter;
thread_pool = new ThreadPool( "TrackerServer:TCP:"+port, THREAD_POOL_SIZE );
if ( PROCESSING_GET_LIMIT > 0 ){
thread_pool.setExecutionLimit( PROCESSING_GET_LIMIT );
}
}
public void
runProcessor(
TRTrackerServerProcessorTCP processor )
{
thread_pool.run( processor );
}
protected boolean
isIPFilterEnabled()
{
return( apply_ip_filter );
}
static boolean LOG_DOS_TO_FILE = false;
static{
LOG_DOS_TO_FILE = System.getProperty("azureus.log.dos") != null;
}
protected static File dos_log_file;
protected static AEMonitor class_mon = new AEMonitor( "TRTrackerServerTCP:class" );
Map DOS_map =
new LinkedHashMap( 1000, (float)0.75, true )
{
protected boolean
removeEldestEntry(
Map.Entry eldest)
{
return( checkDOSRemove( eldest ));
}
};
List dos_list = new ArrayList(128);
long last_dos_check = 0;
long MAX_DOS_ENTRIES = 10000;
long MAX_DOS_RETENTION = 10000;
int DOS_CHECK_DEAD_WOOD_COUNT = 512;
int DOS_MIN_INTERVAL = 1000;
int dos_check_count = 0;
protected boolean
checkDOS(
String ip )
throws UnknownHostException
{
InetAddress inet_address = InetAddress.getByName(ip);
if ( inet_address.isLoopbackAddress() || InetAddress.getLocalHost().equals( inet_address )){
return( false);
}
boolean res;
last_dos_check = SystemTime.getCurrentTime();
DOSEntry entry = (DOSEntry)DOS_map.get(ip);
if ( entry == null ){
entry = new DOSEntry(ip);
DOS_map.put( ip, entry );
res = false;
}else{
res = last_dos_check - entry.last_time < DOS_MIN_INTERVAL;
if ( res && LOG_DOS_TO_FILE ){
dos_list.add( entry );
}
entry.last_time = last_dos_check;
}
// remove dead wood
dos_check_count++;
if ( dos_check_count == DOS_CHECK_DEAD_WOOD_COUNT ){
dos_check_count = 0;
Iterator it = DOS_map.values().iterator();
while( it.hasNext()){
DOSEntry this_entry = (DOSEntry)it.next();
if ( last_dos_check - this_entry.last_time > MAX_DOS_RETENTION ){
it.remove();
}else{
break;
}
}
if ( dos_list.size() > 0 ){
try{
class_mon.enter();
if ( dos_log_file == null ){
dos_log_file = new File( System.getProperty("user.dir" ) + File.separator + "dos.log" );
}
PrintWriter pw = null;
try{
pw = new PrintWriter( new FileWriter( dos_log_file, true ));
for (int i=0;i<dos_list.size();i++){
DOSEntry this_entry = (DOSEntry)dos_list.get(i);
String ts = new SimpleDateFormat("HH:mm:ss - ").format( new Date(this_entry.last_time ));
pw.println( ts + this_entry.ip );
}
}catch( Throwable e ){
}finally{
dos_list.clear();
if ( pw != null ){
try{
pw.close();
}catch( Throwable e ){
}
}
}
}finally{
class_mon.exit();
}
}
}
return( res );
}
protected boolean
checkDOSRemove(
Map.Entry eldest )
{
boolean res = DOS_map.size() > MAX_DOS_ENTRIES ||
last_dos_check - ((DOSEntry)eldest.getValue()).last_time > MAX_DOS_RETENTION;
return( res );
}
protected class
DOSEntry
{
String ip;
long last_time;
protected
DOSEntry(
String _ip )
{
ip = _ip;
last_time = last_dos_check;
}
}
public int
getPort()
{
return( port );
}
protected void
setPort(
int _port )
{
port = _port;
}
public String
getHost()
{
return( COConfigurationManager.getStringParameter( "Tracker IP", "" ));
}
public boolean
isSSL()
{
return( ssl );
}
protected boolean
handleExternalRequest(
final InetSocketAddress local_address,
final InetSocketAddress client_address,
final String user,
final String url,
final URL absolute_url,
final String header,
final InputStream is,
final OutputStream os,
final AsyncController async,
final boolean[] keep_alive )
throws IOException
{
final boolean original_ka = keep_alive[0];
keep_alive[0] = false;
for ( TRTrackerServerListener listener: listeners ){
if ( listener.handleExternalRequest( client_address, user, url, absolute_url, header, is, os, async )){
return( true );
}
}
for ( TRTrackerServerListener2 listener: listeners2 ){
TRTrackerServerListener2.ExternalRequest request =
new TRTrackerServerListener2.ExternalRequest()
{
public InetSocketAddress
getClientAddress()
{
return( client_address );
}
public InetSocketAddress
getLocalAddress()
{
return( local_address );
}
public String
getUser()
{
return( user );
}
public String
getURL()
{
return( url );
}
public URL
getAbsoluteURL()
{
return( absolute_url );
}
public String
getHeader()
{
return( header );
}
public InputStream
getInputStream()
{
return( is );
}
public OutputStream
getOutputStream()
{
return( os );
}
public AsyncController
getAsyncController()
{
return( async );
}
public boolean
canKeepAlive()
{
return( original_ka );
}
public void
setKeepAlive(
boolean ka )
{
keep_alive[0] = original_ka && ka;
}
};
if ( listener.handleExternalRequest( request )){
return( true );
}
}
return( false );
}
}