Package com.aelitis.net.udp.uc.impl

Source Code of com.aelitis.net.udp.uc.impl.PRUDPPacketHandlerSocks

/*
* Created on Jun 8, 2010
* Created by Paul Gardner
*
* Copyright 2010 Vuze, Inc.  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; version 2 of the License only.
*
* 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.
*/


package com.aelitis.net.udp.uc.impl;

import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.PasswordAuthentication;
import java.net.Proxy;
import java.net.Socket;

import org.gudy.azureus2.core3.config.COConfigurationManager;
import org.gudy.azureus2.core3.config.ParameterListener;
import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.core3.util.HostNameToIPResolver;

import com.aelitis.azureus.core.proxy.AEProxyFactory;
import com.aelitis.net.udp.uc.PRUDPPacket;
import com.aelitis.net.udp.uc.PRUDPPacketHandler;
import com.aelitis.net.udp.uc.PRUDPPacketHandlerException;
import com.aelitis.net.udp.uc.PRUDPPacketHandlerStats;
import com.aelitis.net.udp.uc.PRUDPPacketReceiver;
import com.aelitis.net.udp.uc.PRUDPPrimordialHandler;
import com.aelitis.net.udp.uc.PRUDPRequestHandler;

public class
PRUDPPacketHandlerSocks
  implements PRUDPPacketHandler, PRUDPPacketHandlerImpl.PacketTransformer
{
  private static String  socks_host;
  private static int    socks_port;
  private static String  socks_user;
  private static String  socks_password;
 
  static{
    COConfigurationManager.addAndFireParameterListeners(
      new String[]{
        "Proxy.Host",
        "Proxy.Port",
        "Proxy.Username",
        "Proxy.Password",
      },
      new ParameterListener()
      {
        public void
        parameterChanged(
          String parameter_name )
        {
            socks_host     = COConfigurationManager.getStringParameter("Proxy.Host").trim();
          socks_port     = Integer.parseInt(COConfigurationManager.getStringParameter("Proxy.Port").trim());
          socks_user     = COConfigurationManager.getStringParameter("Proxy.Username").trim();
          socks_password   = COConfigurationManager.getStringParameter("Proxy.Password").trim();
                  
          if ( socks_user.equalsIgnoreCase("<none>")){
            socks_user = "";
          }
                 
        }
      });
  }
 
  final private InetSocketAddress    target;
 
  private Socket          control_socket;
 
  private InetSocketAddress    relay;
 
  private PRUDPPacketHandler    delegate;
 
  private byte[]  packet_out_header;
 
  protected
  PRUDPPacketHandlerSocks(
    InetSocketAddress    _target )
 
    throws PRUDPPacketHandlerException
  {
    target  = _target;
   
    boolean  ok = false;
   
    try{
        delegate = new PRUDPPacketHandlerImpl( 0, null, this );

      control_socket = new Socket( Proxy.NO_PROXY );
     
      control_socket.connect( new InetSocketAddress( socks_host, socks_port ));
   
      DataOutputStream   dos = new DataOutputStream( new BufferedOutputStream( control_socket.getOutputStream(), 256 ));
      DataInputStream   dis = new DataInputStream( control_socket.getInputStream());
           
      dos.writeByte( (byte)5 ); // socks 5
      dos.writeByte( (byte)2 ); // 2 methods
      dos.writeByte( (byte)0 ); // no auth
      dos.writeByte( (byte)2 ); // user/pw
     
      dos.flush();
     
        dis.readByte()// version byte
       
        byte method = dis.readByte();

        if ( method != 0 && method != 2 ){
         
            throw new IOException( "SOCKS 5: no valid method [" + method + "]" );
        }

          // auth
       
        if ( method == 2 ) {
           
          dos.writeByte( (byte)1 ); // user/pw version
          dos.writeByte( (byte)socks_user.length() ); // user length
          dos.write( socks_user.getBytes() );
          dos.writeByte( (byte)socks_password.length() ); // password length
          dos.write( socks_password.getBytes() );

          dos.flush();
         
          dis.readByte()// version byte
         
          byte status = dis.readByte();

            if ( status != 0 ){
             
              throw( new IOException( "SOCKS 5: authentication fails [status=" +status+ "]" ));
            }
        }
       
        String  mapped_ip;
       
        if ( target.isUnresolved() || target.getAddress() == null ){
         
            // deal with long "hostnames" that we get for, e.g., I2P destinations
         
            mapped_ip = AEProxyFactory.getAddressMapper().internalise( target.getHostName() );
           
        }else{
           
            mapped_ip = target.getAddress().getHostName();
        }
       
        dos.writeByte( (byte)5 ); // version
        dos.writeByte( (byte)3 ); // udp associate
        dos.writeByte( (byte)0 ); // reserved
       
        dos.writeByte((byte)1);
        dos.write( new byte[4] );
       
        dos.writeShort( (short)delegate.getPort()); // port
       
        dos.flush();
       
        dis.readByte()// ver
       
        byte reply = dis.readByte();
       
        if ( reply != 0 ){
         
            throw( new IOException( "SOCKS 5: udp association fails [reply=" +reply+ "]" ));
        }
       
        dis.readByte()// reserved
       
        InetAddress  relay_address;
       
        byte atype = dis.readByte();
       
        if ( atype == 1 ){
         
          byte[]  bytes = new byte[4];
         
          dis.readFully( bytes );
         
          relay_address = InetAddress.getByAddress( bytes );
         
        }else if ( atype == 3 ){
         
          byte  len = dis.readByte();
         
          byte[] bytes = new byte[(int)len&0xff ];
         
          dis.readFully( bytes );
         
          relay_address = InetAddress.getByName( new String( bytes ));
         
        }else{
         
          byte[]  bytes = new byte[16];
         
          dis.readFully( bytes );
         
          relay_address = InetAddress.getByAddress( bytes );

        }
       
        int  relay_port = ((dis.readByte()<<8)&0xff00) | (dis.readByte() & 0x00ff );
         
        if ( relay_address.isAnyLocalAddress()){
         
          relay_address = control_socket.getInetAddress();
        }
       
        relay = new InetSocketAddress( relay_address, relay_port );
                 
          // use the maped ip for dns resolution so we don't leak the
          // actual address if this is a secure one (e.g. I2P one)
       
        ByteArrayOutputStream  baos_temp     = new ByteArrayOutputStream();
        DataOutputStream    dos_temp  = new DataOutputStream( baos_temp );
 
        dos_temp.writeByte(0)// resv
        dos_temp.writeByte(0)// resv       
        dos_temp.writeByte(0)// frag (none)
 
        try {
          byte[] ip_bytes = HostNameToIPResolver.syncResolve( mapped_ip ).getAddress();
 
          dos_temp.writeByte( ip_bytes.length==4?(byte)1:(byte)4 );
          dos_temp.write( ip_bytes );
 
         
        }catch( Throwable e ){
                   
          dos_temp.writeByte( (byte)3 )// address type = domain name
          dos_temp.writeByte( (byte)mapped_ip.length() )// address type = domain name
          dos_temp.write( mapped_ip.getBytes() );
 
        }
 
        dos_temp.writeShort( (short)target.getPort() ); // port
 
        dos_temp.flush();
        packet_out_header = baos_temp.toByteArray();

             
      ok = true;
     
      Thread.sleep(1000);
     
    }catch( Throwable e ){
     
      throw( new PRUDPPacketHandlerException( "socks setup failed: " + Debug.getNestedExceptionMessage(e), e));
     
    }finally{
     
      if ( !ok ){
       
        try{
          control_socket.close();
         
        }catch( Throwable e ){
         
          Debug.out( e );
         
        }finally{
         
          control_socket = null;
        }
       
        if ( delegate != null ){
         
          try{
              delegate.destroy();
             
          }finally{
           
            delegate = null;
          }
        }
      }
    }
  }
 
  public void
  transformSend(
    DatagramPacket  packet )
  {   
    byte[]  data     = packet.getData();
    int    data_len  = packet.getLength();
   
    byte[]  new_data = new byte[data_len+packet_out_header.length];
   
    System.arraycopy( packet_out_header, 0, new_data, 0, packet_out_header.length );
    System.arraycopy( data, 0, new_data, packet_out_header.length, data_len);
   
    packet.setData( new_data );
  }
   
  public void
  transformReceive(
    DatagramPacket  packet )
  {
    byte[]  data     = packet.getData();
    int    data_len  = packet.getLength();
   
    DataInputStream dis = new DataInputStream( new ByteArrayInputStream( data, 0, data_len ));
   
    try{
      dis.readByte()// res
      dis.readByte()// res
      dis.readByte()// assume no frag
   
      byte  atype = dis.readByte();
     
      int  encap_len = 4;
      if ( atype == 1 ){
       
        encap_len += 4;
       
      }else if ( atype == 3 ){
       
        encap_len += 1 + (dis.readByte()&0xff);
       
      }else{
       
        encap_len += 16;
      }
     
      encap_len += 2// port
     
      byte[]  new_data = new byte[data_len-encap_len];
     
      System.arraycopy( data, encap_len, new_data, 0, data_len - encap_len );
     
      packet.setData( new_data );
     
    }catch( IOException e ){
     
      Debug.out( e );
    }
  }
     
  private void
  checkAddress(
    InetSocketAddress      destination )
 
    throws PRUDPPacketHandlerException
  {
    if ( !destination.equals( target )){
     
      throw( new PRUDPPacketHandlerException( "Destination mismatch" ));
    }
  }
 
  public void
  sendAndReceive(
    PRUDPPacket          request_packet,
    InetSocketAddress      destination_address,
    PRUDPPacketReceiver      receiver,
    long            timeout,
    int              priority )
 
    throws PRUDPPacketHandlerException
  {
    checkAddress( destination_address );
   
    delegate.sendAndReceive( request_packet, relay, receiver, timeout, priority );
  }
 
  public PRUDPPacket
  sendAndReceive(
    PasswordAuthentication    auth,
    PRUDPPacket          request_packet,
    InetSocketAddress      destination_address )
 
    throws PRUDPPacketHandlerException
  {
    checkAddress( destination_address );
   
    return( delegate.sendAndReceive( auth, request_packet, relay));
  }
 
  public PRUDPPacket
  sendAndReceive(
    PasswordAuthentication    auth,
    PRUDPPacket          request_packet,
    InetSocketAddress      destination_address,
    long            timeout_millis )
 
    throws PRUDPPacketHandlerException
  {
    checkAddress( destination_address );
   
    return( delegate.sendAndReceive(auth, request_packet, relay, timeout_millis ));
  }
 
  public PRUDPPacket
  sendAndReceive(
    PasswordAuthentication    auth,
    PRUDPPacket          request_packet,
    InetSocketAddress      destination_address,
    long            timeout_millis,
    int              priority )
 
    throws PRUDPPacketHandlerException
  {
    checkAddress( destination_address );
   
    return( delegate.sendAndReceive(auth, request_packet, relay, timeout_millis, priority ));
  }
 
  public void
  send(
    PRUDPPacket          request_packet,
    InetSocketAddress      destination_address )
 
    throws PRUDPPacketHandlerException
  {
    checkAddress( destination_address );
   
    delegate.send( request_packet, relay );
  }
 
  public PRUDPRequestHandler
  getRequestHandler()
  {
    return( delegate.getRequestHandler());
  }
 
  public void
  setRequestHandler(
    PRUDPRequestHandler  request_handler )
  {
    delegate.setRequestHandler( request_handler );
  }
 
  public void
  primordialSend(
    byte[]        data,
    InetSocketAddress  target )
 
    throws PRUDPPacketHandlerException
  {
    throw( new PRUDPPacketHandlerException( "not imp" ));
  }
 
  public void
  addPrimordialHandler(
    PRUDPPrimordialHandler  handler )
  {
  }
 
  public void
  removePrimordialHandler(
    PRUDPPrimordialHandler  handler )
  {
  }
 
  public int
  getPort()
  {
    return( delegate.getPort());
  }
 
  public void
  setDelays(
    int    send_delay,
    int    receive_delay,
    int    queued_request_timeout )
  {
    delegate.setDelays(send_delay, receive_delay, queued_request_timeout);
  }
 
  public void
  setExplicitBindAddress(
    InetAddress  address )
  {
    delegate.setExplicitBindAddress( address );
  }
 
  public PRUDPPacketHandlerStats
  getStats()
  {
    return( delegate.getStats());
  }
 
  public PRUDPPacketHandler
  openSession(
    InetSocketAddress  target )
 
    throws PRUDPPacketHandlerException
  {
    throw( new PRUDPPacketHandlerException( "not supported" ));
  }
 
  public void
  closeSession()
 
    throws PRUDPPacketHandlerException
 
    if ( control_socket != null ){
     
      try{
        control_socket.close();
       
        control_socket = null;
       
      }catch( Throwable e ){
       
        Debug.out( e );
      }
    }
   
    if ( delegate != null ){
     
      delegate.destroy();
    }
  }
 
  public void
  destroy()
  {
    try{
      closeSession();
     
    }catch( Throwable e ){
     
      Debug.out( e );
    }
  }
}
TOP

Related Classes of com.aelitis.net.udp.uc.impl.PRUDPPacketHandlerSocks

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.