FileDocCategorySizeDatePackage
NatCheckerServer.javaAPI DocAzureus 3.0.3.49117Mon Mar 05 14:57:18 GMT 2007org.gudy.azureus2.core3.ipchecker.natchecker

NatCheckerServer

public class NatCheckerServer extends AEThread

Fields Summary
private static final LogIDs
LOGID
private static final String
incoming_handshake
private final InetAddress
bind_ip
private boolean
bind_ip_set
private final String
check
private final boolean
http_test
private ServerSocket
server
private volatile boolean
bContinue
private final boolean
use_incoming_router
private NetworkManager.ByteMatcher
matcher
Constructors Summary
public NatCheckerServer(InetAddress _bind_ip, int _port, String _check, boolean _http_test)

    
    
     
    
    	 	 
    	 			  
    	 			 
    	 		 
    
    	 
         
      super("Nat Checker Server");
      
      bind_ip		= _bind_ip;
      check		 	= _check;
      http_test		= _http_test;
      
      if ( http_test ){
    	  
    	  HTTPNetworkManager	net_man = HTTPNetworkManager.getSingleton();
    	  
    	  if ( net_man.isHTTPListenerEnabled()){
       	  
    		  use_incoming_router = _port == net_man.getHTTPListeningPortNumber();
    		  
    	  }else{
    		  
    		  use_incoming_router = false;
    	  }
 
    	  if ( use_incoming_router ){
    		  
    		  if ( !net_man.isEffectiveBindAddress( bind_ip )){
    			  
    			  net_man.setExplicitBindAddress( bind_ip );
    			  
    			  bind_ip_set	= true;
    		  }
    	  }
      }else{
    	
    	  TCPNetworkManager	net_man = TCPNetworkManager.getSingleton();

      	  if ( net_man.isTCPListenerEnabled()){
           	  
    		  use_incoming_router = _port == net_man.getTCPListeningPortNumber();
    		  
    	  }else{
    		  
    		  use_incoming_router = false;
    	  }  
      	  
	      if ( use_incoming_router ) {
	 
 		 	if ( !net_man.isEffectiveBindAddress( bind_ip )){
    			  
    			  net_man.setExplicitBindAddress( bind_ip );
    			  
    			  bind_ip_set	= true;
    		  }
 		  
	    	  	//test port and currently-configured listening port are the same,
	    	  	//so register for incoming connection routing
	        
	        matcher = new NetworkManager.ByteMatcher() {
			  public int matchThisSizeOrBigger(){ return( maxSize()); }
	          public int maxSize() {  return incoming_handshake.getBytes().length;  }
	          public int minSize(){ return maxSize(); }
	        
	          public Object matches( TransportHelper transport, ByteBuffer to_compare, int port ) {             
	            int old_limit = to_compare.limit();
	            to_compare.limit( to_compare.position() + maxSize() );
	            boolean matches = to_compare.equals( ByteBuffer.wrap( incoming_handshake.getBytes() ) );
	            to_compare.limit( old_limit );  //restore buffer structure
	            return matches?"":null;
	          }
	          public Object minMatches( TransportHelper transport, ByteBuffer to_compare, int port ) { return( matches( transport, to_compare, port )); } 
	          public byte[][] getSharedSecrets(){ return( null ); }
	  	   	  public int getSpecificPort(){return( -1 );
			}
	        };
	        
	        NetworkManager.getSingleton().requestIncomingConnectionRouting(
	            matcher,
	            new NetworkManager.RoutingListener() {
	              public void 
	              connectionRouted( 
	            	NetworkConnection 	connection, 
	            	Object 				routing_data ) 
	              {
	            	  if (Logger.isEnabled())
	            		  Logger.log(new LogEvent(LOGID, "Incoming connection from ["
	            				  + connection + "] successfully routed to NAT CHECKER"));
	
	            	  try{
	            		  ByteBuffer	msg = getMessage();
	
	            		  Transport transport = connection.getTransport();
	
	            		  long	start = SystemTime.getCurrentTime();
	
	            		  while( msg.hasRemaining()){
	
	            			  transport.write( new ByteBuffer[]{ msg }, 0, 1 );
	
	            			  if ( msg.hasRemaining()){
	
	            				  long now = SystemTime.getCurrentTime();
	
	            				  if ( now < start ){
	
	            					  start = now;
	
	            				  }else{
	
	            					  if ( now - start > 30000 ){
	
	            						  throw( new Exception( "Timeout" ));
	            					  }
	            				  }
	
	            				  Thread.sleep( 50 );
	            			  }
	            		  }
	            	  }catch( Throwable t ) {
	            		
	            		  Debug.out( "Nat check write failed", t );
	            	  }
	
	            	  connection.close();
	              }
	              
	              public boolean
	          	  autoCryptoFallback()
	              {
	            	  return( true );
	              }
	            },
	            new MessageStreamFactory() {
	              public MessageStreamEncoder createEncoder() {  return new AZMessageEncoder(false);  /* unused */}
	              public MessageStreamDecoder createDecoder() {  return new AZMessageDecoder();  /* unused */}
	            });
	      }
          		
	      if (Logger.isEnabled())
  				Logger.log(new LogEvent(LOGID, "NAT tester using central routing for "
  						+ "server socket"));
      }
      
      if ( !use_incoming_router ){
     
    	  //different port than already listening on, start new listen server
    	  
        try{
 
          server = new ServerSocket();  //unbound          
          server.setReuseAddress( true );  //set SO_REUSEADDR 
          
          InetSocketAddress address;

          if( bind_ip != null ) {
        	  
        	  address = new InetSocketAddress( bind_ip, _port );
        	  
          }else {
        	  
        	  address = new InetSocketAddress( _port );
          }
       
  	      server.bind( address );
  	      
  	      if (Logger.isEnabled())	Logger.log(new LogEvent(LOGID, "NAT tester server socket bound to " +address ));
          
 
        }catch(Exception e) { 
        	
        	Logger.log(new LogEvent(LOGID, "NAT tester failed to setup listener socket", e ));
        	
        	throw( e );   
        }
      }
    
Methods Summary
protected java.nio.ByteBuffergetMessage()

		  Map	map = new HashMap();

		  map.put( "check", check );

		  byte[]	map_bytes = BEncoder.encode( map );

		  ByteBuffer msg = ByteBuffer.allocate( 4 + map_bytes.length );

		  msg.putInt( map_bytes.length );
		  msg.put( map_bytes );

		  msg.flip();
		  
		  return( msg );
    
public voidrunSupport()

      while(bContinue) {
        try {
          if (use_incoming_router) {
            //just NOOP loop sleep while waiting for routing
            Thread.sleep(20);
          }
          else {
            //listen for accept
          	Socket sck = server.accept();
          	
          	sck.getOutputStream().write( getMessage().array());
          	
          	sck.close();
          }
        } catch(Exception e) {
        	//Debug.printStackTrace(e);
        	bContinue = false;
        }
      }
    
public voidstopIt()

      bContinue = false;
      
      if( use_incoming_router ) {
    	  
    	  if ( http_test ){
    		  
    		  if ( bind_ip_set ){
    			  
    			  HTTPNetworkManager.getSingleton().clearExplicitBindAddress();
    		  }
    	  }else{
    		  
    		  NetworkManager.getSingleton().cancelIncomingConnectionRouting( matcher );
    		  
    		  if ( bind_ip_set ){
    			  
    			  TCPNetworkManager.getSingleton().clearExplicitBindAddress();
    		  }
    	  }
      }
      else if( server != null ) {
        try {
          server.close();
        }
        catch(Throwable t) { t.printStackTrace(); }
      }