Package org.gudy.azureus2.core3.ipchecker.natchecker

Source Code of org.gudy.azureus2.core3.ipchecker.natchecker.NatCheckerServer

/*
* File    : NatCheckerServer.java
* Created : 12 oct. 2003 19:05:09
* By      : Olivier
*
* 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.ipchecker.natchecker;

import java.io.IOException;
import java.net.*;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;

import org.gudy.azureus2.core3.logging.*;
import org.gudy.azureus2.core3.util.*;

import com.aelitis.azureus.core.networkmanager.*;
import com.aelitis.azureus.core.networkmanager.impl.TransportHelper;
import com.aelitis.azureus.core.networkmanager.impl.http.HTTPNetworkManager;
import com.aelitis.azureus.core.networkmanager.impl.tcp.TCPNetworkManager;
import com.aelitis.azureus.core.peermanager.messaging.*;
import com.aelitis.azureus.core.peermanager.messaging.azureus.*;



/**
*
*
*/
public class NatCheckerServer extends AEThread {
  private static final LogIDs LOGID = LogIDs.NET;
    private static final String incoming_handshake = "NATCHECK_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 = true;
    private final boolean use_incoming_router;
    private NetworkManager.ByteMatcher matcher;
   
   
    public
    NatCheckerServer(
      InetAddress   _bind_ip,
      int       _port, 
      String       _check,
      boolean     _http_test )
   
      throws Exception
    {    
      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( null );
                }
               
                public boolean
                autoCryptoFallback()
                {
                  return( true );
                }
              },
              new MessageStreamFactory() {
                public MessageStreamEncoder createEncoder() {  return new AZMessageEncoder(AZMessageEncoder.PADDING_MODE_NONE)/* 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 );  
        }
      }
    }
   
    protected ByteBuffer
    getMessage()
   
      throws IOException
    {
      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 void runSupport() {
      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 void stopIt() {
      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(); }
      }
    }
   
   
  }
TOP

Related Classes of org.gudy.azureus2.core3.ipchecker.natchecker.NatCheckerServer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.