/*
* Created on Mar 20, 2004
* Created by Alon Rohter
* Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
*
* 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, or (at your option) any later version.
* 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.
* 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.
*
* AELITIS, SAS au capital de 46,603.30 euros
* 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
*
*/
package org.gudy.azureus2.core3.peer.util;
import java.net.InetAddress;
import java.util.*;
import org.gudy.azureus2.core3.config.*;
import org.gudy.azureus2.core3.peer.PEPeer;
import org.gudy.azureus2.core3.util.Constants;
import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.core3.util.SystemTime;
import org.gudy.azureus2.plugins.peers.Peer;
import org.gudy.azureus2.plugins.utils.LocationProvider;
import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils;
import com.aelitis.azureus.core.AzureusCoreFactory;
/**
* Varies peer connection utility methods.
*/
public class PeerUtils {
private static final String CONFIG_MAX_CONN_PER_TORRENT = "Max.Peer.Connections.Per.Torrent";
private static final String CONFIG_MAX_CONN_TOTAL = "Max.Peer.Connections.Total";
public static int MAX_CONNECTIONS_PER_TORRENT;
public static int MAX_CONNECTIONS_TOTAL;
static{
COConfigurationManager.addParameterListener(
CONFIG_MAX_CONN_PER_TORRENT,
new ParameterListener()
{
public void
parameterChanged(
String parameterName )
{
MAX_CONNECTIONS_PER_TORRENT = COConfigurationManager.getIntParameter(CONFIG_MAX_CONN_PER_TORRENT);
}
});
MAX_CONNECTIONS_PER_TORRENT = COConfigurationManager.getIntParameter(CONFIG_MAX_CONN_PER_TORRENT);
COConfigurationManager.addParameterListener(
CONFIG_MAX_CONN_TOTAL,
new ParameterListener()
{
public void
parameterChanged(
String parameterName )
{
MAX_CONNECTIONS_TOTAL = COConfigurationManager.getIntParameter(CONFIG_MAX_CONN_TOTAL);
}
});
MAX_CONNECTIONS_TOTAL = COConfigurationManager.getIntParameter(CONFIG_MAX_CONN_TOTAL);
}
/**
* Get the number of new peer connections allowed for the given data item,
* within the configured per-torrent and global connection limits.
* @return max number of new connections allowed, or -1 if there is no limit
*/
public static int numNewConnectionsAllowed( PeerIdentityDataID data_id, int specific_max ) {
int curConnPerTorrent = PeerIdentityManager.getIdentityCount( data_id );
int curConnTotal = PeerIdentityManager.getTotalIdentityCount();
// specific max here will default to the global per-torrent default if not explicitly set
// so we don't need to consider CONFIG_MAX_CONN_PER_TORRENT seperately
int PER_TORRENT_LIMIT = specific_max;
int perTorrentAllowed = -1; //default unlimited
if ( PER_TORRENT_LIMIT != 0 ) { //if limited
int allowed = PER_TORRENT_LIMIT - curConnPerTorrent;
if ( allowed < 0 ) allowed = 0;
perTorrentAllowed = allowed;
}
int totalAllowed = -1; //default unlimited
if ( MAX_CONNECTIONS_TOTAL != 0 ) { //if limited
int allowed = MAX_CONNECTIONS_TOTAL - curConnTotal;
if ( allowed < 0 ) allowed = 0;
totalAllowed = allowed;
}
int allowed = -1; //default unlimited
if ( perTorrentAllowed > -1 && totalAllowed > -1 ) { //if both limited
allowed = Math.min( perTorrentAllowed, totalAllowed );
}
else if ( perTorrentAllowed == -1 || totalAllowed == -1 ) { //if either unlimited
allowed = Math.max( perTorrentAllowed, totalAllowed );
}
return allowed;
}
private static Set<Integer> ignore_peer_ports = new HashSet<Integer>();
static{
COConfigurationManager.addParameterListener(
"Ignore.peer.ports",
new ParameterListener()
{
public void
parameterChanged(
String parameterName )
{
readIgnorePeerPorts();
}
});
readIgnorePeerPorts();
}
private static void
readIgnorePeerPorts()
{
// XXX Optimize me for ranges!!
String str = COConfigurationManager.getStringParameter( "Ignore.peer.ports" ).trim();
ignore_peer_ports.clear();
if ( str.length() > 0 ){
String[] ports = str.split("\\;");
if (ports != null && ports.length > 0) {
for (int i = 0; i < ports.length; i++) {
String port = ports[i];
int spreadPos = port.indexOf('-');
if (spreadPos > 0 && spreadPos < port.length() - 1) {
try {
int iMin = Integer.parseInt(port.substring(0, spreadPos).trim());
int iMax = Integer.parseInt(port.substring(spreadPos + 1).trim());
iMin = Math.max( 0, iMin );
iMax = Math.min(65535, iMax );
for (int j = iMin; j <= iMax; j++) {
ignore_peer_ports.add(Integer.valueOf(j));
}
} catch (Throwable e) {
Debug.out( "Invalid ignore-port entry: " + port );
}
} else {
try{
ignore_peer_ports.add(Integer.parseInt(port.trim()));
} catch (Throwable e) {
Debug.out( "Invalid ignore-port entry: " + port );
}
}
}
}
}
}
public static boolean
ignorePeerPort(
int port )
{
return( ignore_peer_ports.contains( port ));
}
static final String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
public static byte[]
createPeerID()
{
byte[] peerId = new byte[20];
byte[] version = Constants.VERSION_ID;
for (int i = 0; i < 8; i++) {
peerId[i] = version[i];
}
for (int i = 8; i < 20; i++) {
int pos = (int) ( Math.random() * chars.length());
peerId[i] = (byte)chars.charAt(pos);
}
// System.out.println( "generated new peer id:" + ByteFormatter.nicePrint(peerId));
return( peerId );
}
public static byte[]
createWebSeedPeerID()
{
byte[] peerId = new byte[20];
peerId[0] = '-';
peerId[1] = 'W';
peerId[2] = 'S';
for (int i = 3; i < 20; i++) {
int pos = (int) ( Math.random() * chars.length());
peerId[i] = (byte)chars.charAt(pos);
}
// System.out.println( "generated new peer id:" + ByteFormatter.nicePrint(peerId));
return( peerId );
}
private static volatile LocationProvider country_provider;
private static long country_provider_last_check;
private static Object country_key = new Object();
private static LocationProvider
getCountryProvider()
{
if ( country_provider != null ){
if ( country_provider.isDestroyed()){
country_provider = null;
country_provider_last_check = 0;
}
}
if ( country_provider == null ){
long now = SystemTime.getMonotonousTime();
if ( country_provider_last_check == 0 || now - country_provider_last_check > 20*1000 ){
country_provider_last_check = now;
java.util.List<LocationProvider> providers = AzureusCoreFactory.getSingleton().getPluginManager().getDefaultPluginInterface().getUtilities().getLocationProviders();
for ( LocationProvider provider: providers ){
if ( provider.hasCapabilities(
LocationProvider.CAP_ISO3166_BY_IP |
LocationProvider.CAP_COUNTY_BY_IP )){
country_provider = provider;
}
}
}
}
return( country_provider );
}
public static String[]
getCountryDetails(
Peer peer )
{
return( getCountryDetails( PluginCoreUtils.unwrap( peer )));
}
public static String[]
getCountryDetails(
PEPeer peer )
{
if ( peer == null ){
return( null );
}
String[] details = (String[])peer.getUserData( country_key );
if ( details == null ){
LocationProvider lp = getCountryProvider();
if ( lp != null ){
try{
InetAddress peer_address = InetAddress.getByName( peer.getIp());
String code = lp.getISO3166CodeForIP( peer_address );
String name = lp.getCountryNameForIP( peer_address, Locale.getDefault());
if ( code != null && name != null ){
details = new String[]{ code, name };
}else{
details = new String[0];
}
peer.setUserData( country_key, details );
}catch( Throwable e ){
}
}
}
return( details );
}
}