FileDocCategorySizeDatePackage
NetworkAdminSpeedTestScheduledTestImpl.javaAPI DocAzureus 3.0.3.428411Tue Jul 10 12:49:46 BST 2007com.aelitis.azureus.core.networkmanager.admin.impl

NetworkAdminSpeedTestScheduledTestImpl

public class NetworkAdminSpeedTestScheduledTestImpl extends Object implements com.aelitis.azureus.core.networkmanager.admin.NetworkAdminSpeedTestScheduledTest

Fields Summary
private static final long
REQUEST_TEST
private static final long
CHALLENGE_REPLY
private static final long
TEST_RESULT
private static int
ZERO_DOWNLOAD_SETTING
private org.gudy.azureus2.plugins.PluginInterface
plugin
private NetworkAdminSpeedTesterImpl
tester
private String
detectedRouter
private SpeedTestDownloadState
preTestSettings
private byte[]
challenge_id
private long
delay_millis
private long
max_speed
private org.gudy.azureus2.core3.torrent.TOTorrent
test_torrent
private volatile boolean
aborted
private com.aelitis.azureus.core.util.CopyOnWriteList
listeners
Constructors Summary
protected NetworkAdminSpeedTestScheduledTestImpl(org.gudy.azureus2.plugins.PluginInterface _plugin, NetworkAdminSpeedTesterImpl _tester)

	
	
	
								
					 
	
		plugin		= _plugin;
		tester		= _tester;
	    
        	//detect the router.
		
        PluginInterface upnp = plugin.getPluginManager().getPluginInterfaceByClass( UPnPPlugin.class );
        
        if( upnp != null ){
        	
            detectedRouter = upnp.getPluginconfig().getPluginStringParameter("plugin.info");
        }
        
		tester.addListener(
			new NetworkAdminSpeedTesterListener()
			{
				public void 
				complete(
					NetworkAdminSpeedTester 		tester, 
					NetworkAdminSpeedTesterResult 	result )
				{
					try{
						sendResult( result );
		
					}finally{
						
						reportComplete();
					}
				}

				public void 
				stage(
					NetworkAdminSpeedTester 	tester, 
					String 						step ) 
				{
				}
			});
	
Methods Summary
public voidabort()

        abort( MessageText.getString("SpeedTestWizard.abort.message.manual.abort") );
	
public voidabort(java.lang.String reason)

		if ( !aborted ){
			
			aborted	= true;
			
			tester.abort( reason );
		}
	
public voidaddListener(com.aelitis.azureus.core.networkmanager.admin.NetworkAdminSpeedTestScheduledTestListener listener)

		listeners.add( listener );
	
private java.util.MapgetBEncodedMapFromRequest(java.net.URL url)
Read from URL and return byte array.

param
url -
return
byte[] of the results. Max size currently 100k.
throws
java.io.IOException -


        ResourceDownloader rd = ResourceDownloaderFactoryImpl.getSingleton().create( url );

        InputStream is=null;
        Map reply = new HashMap();
        try
        {
            is = rd.download();
            reply = BDecoder.decode( new BufferedInputStream(is) );

            //all replys of this type contains a "result"
            Long res = (Long) reply.get("result");
            if(res==null)
                throw new IllegalStateException("No result parameter in the response!! reply="+reply);
            if(res.intValue()==0){
                StringBuffer msg = new StringBuffer("Server failed. ");
                String error = new String( (byte[]) reply.get("error") );
                String errDetail = new String( (byte[]) reply.get("error_detail") );
                msg.append("Error: ").append(error);
                
                // detail is of no interest to the user
                // msg.append(" ,error detail: ").append(errDetail);
                
                Debug.outNoStack( "SpeedCheck server returned an error: " + error + ", details=" + errDetail );
                
                throw new IOException( msg.toString() );
            }
        }catch(IOException ise){
            //rethrow this type of exception.
            throw ise;
        }catch(Throwable t){
            Debug.out(t);
            Debug.printStackTrace(t);
        }finally{
            try{
                if(is!=null)
                    is.close();
            }catch(Throwable e){
                Debug.printStackTrace(e);
            }
        }
        return reply;
    
public longgetMaxDownBytePerSec()

		return( max_speed );
	
public longgetMaxUpBytePerSec()

		return( max_speed );
	
public com.aelitis.azureus.core.networkmanager.admin.NetworkAdminSpeedTestergetTester()

		return( tester );
	
private java.lang.StringgetVersionFromJAR(java.io.File jar_file)

		try{
				// force the URLClassLoader to load from the URL and not delegate and find the currently
				// jar's Constants
			
			ClassLoader parent = new ClassLoader()
			{
				protected synchronized Class 
				loadClass(
					String 		name,
					boolean		resolve )
				
					throws ClassNotFoundException
				{
					if ( name.equals( "org.gudy.azureus2.core3.util.Constants")){
					
						throw( new ClassNotFoundException());
					}
					
					return( super.loadClass( name, resolve ));
				}
			};
			
			ClassLoader cl = new URLClassLoader(new URL[]{jar_file.toURI().toURL()}, parent);
			
	    	Class c = cl.loadClass( "org.gudy.azureus2.core3.util.Constants");

	    	Field	field = c.getField( "AZUREUS_VERSION" );
	    	
	    	return((String)field.get( null ));
	    	
		}catch( Throwable e){
						
			return( null );
		}
    
private java.util.MaphandleChallengeFromSpeedTestService(java.io.File jar_file, java.util.Map result)

param
jar_file - File Azureus jar used to load classes.
param
result - Map from the previous response
return
Map - from the current response.

        //verify the following items are in the response.

        //size (in bytes)
        //offset (in bytes)
        //challenge_id
        Map retVal = new HashMap();
        RandomAccessFile raf=null;
        try{

            Long size = (Long) result.get("size");
            Long offset = (Long) result.get("offset");
 
            if( size==null || offset==null  )
                throw new IllegalStateException("scheduleTestWithSpeedTestService had a null parameter.");

 
            //read the bytes
            raf = new RandomAccessFile( jar_file, "r" );
            byte[] jarBytes = new byte[size.intValue()];

            raf.seek(offset.intValue());
            raf.read( jarBytes );


            //Build the URL.
            Map request = new HashMap();
            request.put("request_type", new Long(CHALLENGE_REPLY) );
            request.put("challenge_id", challenge_id );
            request.put("data",jarBytes);
 
            retVal = sendRequest( request );

        }finally{
            //close
            try{
                if(raf!=null)
                    raf.close();
            }catch(Throwable t){
                Debug.printStackTrace(t);
            }
        }

        return retVal;
    
public voidremoveListener(com.aelitis.azureus.core.networkmanager.admin.NetworkAdminSpeedTestScheduledTestListener listener)

		listeners.remove( listener );
	
protected voidreportComplete()

		
		resetSpeedLimits();

		Iterator	it = listeners.iterator();
		
		while( it.hasNext()){
			
			try{
				((NetworkAdminSpeedTestScheduledTestListener)it.next()).complete( this );
				
			}catch( Throwable e ){
				
				Debug.printStackTrace( e );
			}
		}
	
protected voidreportStage(java.lang.String str)

		Iterator	it = listeners.iterator();
		
		while( it.hasNext()){
			
			try{
				((NetworkAdminSpeedTestScheduledTestListener)it.next()).stage( this, str );
				
			}catch( Throwable e ){
				
				Debug.printStackTrace( e );
			}
		}
	
protected synchronized voidresetSpeedLimits()
Restore all the downloads the state before the speed test started.

    	if ( preTestSettings != null ){
    	
	        preTestSettings.restoreLimits();
		        
	        preTestSettings = null;
    	}
    
private booleanschedule()
Request a test from the speed testing service, handle the "challenge" if request and then get the id for the test. Per spec all request are BEncoded maps.

return
boolean - true if the test has been reserved with the service.

        try{
            //lookup UPnP devices found. One might be a router.

            //Send "schedule test" request.
            Map request = new HashMap();
            request.put("request_type", new Long(REQUEST_TEST) );

            String id = COConfigurationManager.getStringParameter("ID","unknown");
            
            	// get jar file its version for the test
            
            File	jar_file 		= null;
            String	jar_version		= null;
            
            String	explicit_path = System.getProperty( "azureus.speed.test.challenge.jar.path", null );
            
            if ( explicit_path != null ){
            	
            	File	f = new File( explicit_path );
            	
            	if ( f.exists()){
            		
            		String v = getVersionFromJAR( f );
            		
            		if ( v != null ){
            			
             			jar_file	= f;
            			jar_version	= v;
            			
               			System.out.println( "SpeedTest: using explicit challenge jar " + jar_file.getAbsolutePath() + ", version " + jar_version );
            		}
            	}
            }
            
            if ( jar_file == null ){
            	
                String debug = System.getProperty("debug.speed.test.challenge","n");

                if( !debug.equals( "n" )){
                    
                	//over-ride the jar version, and location for debugging.

                	File f = new File( "C:\\test\\azureus\\Azureus3.0.1.2.jar" );  //ToDo: make this a -D option with this default.

                	if ( f.exists()){
                		
                		jar_file 	= f;
                		jar_version = "3.0.1.2";
                		
              			System.out.println( "SpeedTest: using old spec challenge jar " + jar_file.getAbsolutePath() + ", version " + jar_version );
                	}
                }
            }
            	
            if ( jar_file == null ){
            
            	jar_file = FileUtil.getJarFileFromClass( getClass());

            	if ( jar_file != null ){
            		
            		jar_version = Constants.AZUREUS_VERSION;
            		
          			// System.out.println( "SpeedTest: using class-based challenge jar " + jar_file.getAbsolutePath() + ", version " + jar_version );

            	}else{
            		
            		File f = new File( SystemProperties.getAzureusJarPath());
            		
            		if ( f.exists()){
            			
            			jar_version = Constants.AZUREUS_VERSION;
            			jar_file	= f;
            			
             			// System.out.println( "SpeedTest: using config-based challenge jar " + jar_file.getAbsolutePath() + ", version " + jar_version );
            		}
            	}
            }            
            
            if ( jar_file == null ){
            	
            	throw( new Exception( "Failed to locate an 'Azureus2.jar' to use for the challenge protocol" ));
            }
            
            //ToDo: remove once challenge testing is done.
   
            request.put("az-id",id); //Where to I get the AZ-ID and client version from the Configuration?
            request.put("type","both");
            request.put("jar_ver",jar_version);
 
            if ( detectedRouter != null ){
            	
            	request.put( "router", detectedRouter );
            }
            
            Map result = sendRequest( request );
            
            challenge_id = (byte[]) result.get("challenge_id");

            if( challenge_id == null ){
            	
                throw new IllegalStateException("No challenge returned from speed test scheduling service");
            }
        
            Long responseType =  (Long) result.get("reply_type");

            if( responseType.intValue()==1 ){
                	//a challenge has occured.
                result = handleChallengeFromSpeedTestService( jar_file, result );
                
                responseType = (Long) result.get("reply_type");
            }

            if( responseType == null ){
                throw new IllegalStateException("No challenge response returned from speed test scheduling service");
            }

            if( responseType.intValue()==0 ){
                	//a test has been scheduled.
                	//set the Map properly.
            	
                Long time = (Long) result.get("time");
                Long limit = (Long) result.get("limit");

                if( time==null || limit==null ){
                    throw new IllegalArgumentException("Returned time or limit parameter is null");
                }
                
                delay_millis 	= time.longValue();
                max_speed		= limit.longValue();
                                
                	// this is test-specific data
                
                Map torrentMap = (Map)result.get("torrent");
    	
                test_torrent = TOTorrentFactory.deserialiseFromMap(torrentMap);

                return( true );
            }else{
            	
                throw new IllegalStateException( "Unrecognized response from speed test scheduling servcie." );
            }

        }catch( Throwable t ){
        	       	
            Debug.printStackTrace(t);

            tester.abort( MessageText.getString("SpeedTestWizard.abort.message.scheduling.failed"), t );

            return( false );
        }
    
private java.util.MapsendRequest(java.util.Map request)

        request.put( "ver", new Long(1) );//request version
        request.put( "locale",  MessageText.getCurrentLocale().toString());
        
        String speedTestServiceName = System.getProperty( "speedtest.service.ip.address", Constants.SPEED_TEST_SERVER );

        URL urlRequestTest = new URL("http://"+speedTestServiceName+":60000/scheduletest?request="
                + URLEncoder.encode( new String(BEncoder.encode(request),"ISO-8859-1"),"ISO-8859-1"));
        
        return( getBEncodedMapFromRequest( urlRequestTest ));

    
private voidsendResult(com.aelitis.azureus.core.networkmanager.admin.NetworkAdminSpeedTesterResult result)

    	try{
    		if ( challenge_id != null ){
    			
	    		Map request = new HashMap();
	    		
	    		request.put("request_type", new Long(TEST_RESULT) );
	    		
	    		request.put("challenge_id", challenge_id );
	
    			request.put( "type", new Long( tester.getTestType()));
    			request.put( "mode", new Long( tester.getMode()));
    			request.put( "crypto", new Long( tester.getUseCrypto()?1:0));

	    		if ( result.hadError()){
	    			
	    			request.put( "result", new Long(0));
	    			
	    			request.put( "error", result.getLastError());
	    			
	    		}else{
	    			
	    			request.put( "result", new Long(1));

	    			request.put( "maxup", new Long(result.getUploadSpeed()));
	    			request.put( "maxdown", new Long(result.getDownloadSpeed()));
	    		}
	    		
	    		sendRequest( request );
    		}
    	}catch( Throwable e ){
    		
    		Debug.printStackTrace(e);
    	}
    
protected synchronized voidsetSpeedLimits()
Preserve all the data about the downloads while the test is running.


    		// in case we've already saved limits
    	
    	resetSpeedLimits();
    	
        preTestSettings = new SpeedTestDownloadState();
        
        preTestSettings.saveLimits();
      
public booleanstart()

		if ( schedule()){
		
			new AEThread( "NetworkAdminSpeedTestScheduledTest:delay", true )
			{
				public void
				runSupport()
				{
					long delay_ticks = delay_millis/1000;
			
					for (int i=0;i<delay_ticks;i++){

						if ( aborted ){
			            		
			            	break;
			            }
                        
                        String testScheduledIn = MessageText.getString( "SpeedTestWizard.abort.message.scheduled.in"
                                , new String[]{""+(delay_ticks - i)} );
						reportStage( testScheduledIn );
						
						try{
							Thread.sleep(1000);
							
						}catch( InterruptedException e ){
							
							e.printStackTrace();
						}
					}
					
					if ( !aborted ){
				
						setSpeedLimits();
						
						if ( tester.getTestType() == NetworkAdminSpeedTestScheduler.TEST_TYPE_BT ){
						
							((NetworkAdminSpeedTesterBTImpl)tester).start( test_torrent );
							
						}else{
							String unsupportedType = MessageText.getString("SpeedTestWizard.abort.message.unsupported.type");
							tester.abort(unsupportedType);
						}
					}
				}
			}.start();
			
			return( true );
			
		}else{
		
			return( false );
		}