/* * Created on 1 Nov 2006 * Created by Paul Gardner * Copyright (C) 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 63.529,40 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.util; import java.net.Inet6Address; import java.net.InetAddress; import java.net.NetworkInterface; import java.net.SocketException; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import org.gudy.azureus2.core3.util.AESemaphore; import org.gudy.azureus2.core3.util.AEThread2; 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.pluginsimpl.local.utils.UtilitiesImpl.runnableWithException; public class NetUtils { private static final int MIN_NI_CHECK_MILLIS = 30*1000; private static final int INC1_NI_CHECK_MILLIS = 2*60*1000; private static final int INC2_NI_CHECK_MILLIS = 15*60*1000; private static int current_check_millis = MIN_NI_CHECK_MILLIS; private static long last_ni_check = -1; private static volatile List<NetworkInterface> current_interfaces = new ArrayList<NetworkInterface>(); private static boolean first_check = true; private static boolean check_in_progress; private static AESemaphore ni_sem = new AESemaphore( "NetUtils:ni" ); public static List<NetworkInterface> getNetworkInterfaces() throws SocketException { long now = SystemTime.getMonotonousTime(); boolean do_check = false; boolean is_first = false; synchronized( NetUtils.class ){ if ( !check_in_progress ){ if ( last_ni_check < 0 || now - last_ni_check > current_check_millis ){ do_check = true; check_in_progress = true; if ( first_check ){ first_check = false; is_first = true; } } } } if ( do_check ){ final runnableWithException<SocketException> do_it = new runnableWithException<SocketException>() { public void run() throws SocketException { List<NetworkInterface> result = new ArrayList<NetworkInterface>(); try{ // got some major CPU issues on some machines with crap loads of NIs long start = SystemTime.getHighPrecisionCounter(); Enumeration<NetworkInterface> nis = NetworkInterface.getNetworkInterfaces(); long elapsed_millis = ( SystemTime.getHighPrecisionCounter() - start ) / 1000000; long old_period = current_check_millis; if ( elapsed_millis > (Constants.isAndroid?5000:1000) && current_check_millis < INC2_NI_CHECK_MILLIS ){ current_check_millis = INC2_NI_CHECK_MILLIS; }else if ( elapsed_millis > (Constants.isAndroid?1000:250) && current_check_millis < INC1_NI_CHECK_MILLIS ){ current_check_millis = INC1_NI_CHECK_MILLIS; } if ( old_period != current_check_millis ){ Debug.out( "Network interface enumeration took " + elapsed_millis + ": decreased refresh frequency to " + current_check_millis + "ms" ); } if ( nis != null ){ while( nis.hasMoreElements()){ result.add( nis.nextElement()); } } // System.out.println( "getNI: elapsed=" + elapsed_millis + ", result=" + result.size()); }finally{ synchronized( NetUtils.class ){ check_in_progress = false; current_interfaces = result; last_ni_check = SystemTime.getMonotonousTime(); } ni_sem.releaseForever(); } } }; if ( is_first ){ final AESemaphore do_it_sem = new AESemaphore( "getNIs" ); final SocketException[] error = { null }; new AEThread2( "getNIAsync" ) { public void run() { try{ do_it.run(); }catch( SocketException e ){ error[0] = e; }finally{ do_it_sem.release(); } } }.start(); if ( !do_it_sem.reserve( 15*1000 )){ Debug.out( "Timeout obtaining network interfaces" ); ni_sem.releaseForever(); }else{ if ( error[0] != null ){ throw( error[0] ); } } }else{ do_it.run(); } } ni_sem.reserve(); return( current_interfaces ); } public static InetAddress getLocalHost() throws UnknownHostException { try{ return( InetAddress.getLocalHost()); }catch( Throwable e ){ // sometimes get this when changing host name // return first non-loopback one try{ List<NetworkInterface> nis = getNetworkInterfaces(); for ( NetworkInterface ni: nis ){ Enumeration addresses = ni.getInetAddresses(); while( addresses.hasMoreElements()){ InetAddress address = (InetAddress)addresses.nextElement(); if ( address.isLoopbackAddress() || address instanceof Inet6Address ){ continue; } return( address ); } } }catch( Throwable f ){ } return( InetAddress.getByName( "127.0.0.1" )); } } }