Mega Code Archive

 
Categories / Java / Network Protocol
 

Implements a TCPIP bounce utility (proxy)

/**  * The utillib library.  * More information is available at http://www.jinchess.com/.  * Copyright (C) 2002 Alexander Maryanovsky.  * All rights reserved.  *  * The utillib library is free software; you can redistribute  * it and/or modify it under the terms of the GNU Lesser General Public License  * as published by the Free Software Foundation; either version 2 of the  * License, or (at your option) any later version.  *  * The utillib library 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 Lesser  * General Public License for more details.  *  * You should have received a copy of the GNU Lesser General Public License  * along with utillib library; if not, write to the Free Software  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA  */ import java.io.*; import java.net.Socket; import java.net.ServerSocket; /**  * Implements a TCP/IP bounce utility (proxy). You run bounce specifying which  * port to listen on, which host and on which port to connect to and it will  * act as a proxy relaying information between anyone who connects to it and the  * specified server.  */ public class Bounce{      /**    * The main method.    */   public static void main(String [] args){     if (args.length < 3){       printUsage();       System.exit(1);     }     int localPort;     try{       localPort = Integer.parseInt(args[0]);     } catch (NumberFormatException e){         System.err.println("Bad local port value: "+args[0]);         printUsage();         System.exit(2);         return;       }     String hostname = args[1];     int remotePort;     try{       remotePort = Integer.parseInt(args[2]);     } catch (NumberFormatException e){         System.err.println("Bad remote port value: "+args[2]);         printUsage();         System.exit(3);         return;       }     boolean shouldLog = args.length > 3 ? Boolean.valueOf(args[3]).booleanValue() : false;     int numConnections = 0;     try{       ServerSocket ssock = new ServerSocket(localPort);       while (true){         Socket incomingSock = ssock.accept();         Socket outgoingSock = new Socket(hostname, remotePort);         numConnections++;         InputStream incomingIn = incomingSock.getInputStream();         InputStream outgoingIn = outgoingSock.getInputStream();         OutputStream incomingOut = incomingSock.getOutputStream();         OutputStream outgoingOut = outgoingSock.getOutputStream();         if (shouldLog){           String incomingLogName = "in-log-"+incomingSock.getInetAddress().getHostName()+ "("+localPort+")-" + numConnections + ".dat";           String outgoingLogName = "out-log-" + hostname + "("+remotePort + ")-" + numConnections+".dat";           OutputStream incomingLog = new FileOutputStream(incomingLogName);           incomingOut = new MultiOutputStream(incomingOut, incomingLog);           OutputStream outgoingLog = new FileOutputStream(outgoingLogName);           outgoingOut = new MultiOutputStream(outgoingOut, outgoingLog);         }         PumpThread t1 = new PumpThread(incomingIn, outgoingOut);         PumpThread t2 = new PumpThread(outgoingIn, incomingOut);         t1.start();         t2.start();       }     } catch (IOException e){         e.printStackTrace();         System.exit(3);       }   }   /**    * Dumps usage information to the standard error stream.    */   private static void printUsage(){     System.err.println("Bounce Utility");     System.err.println("Copyright (C) 2002 Alexander Maryanovsky");     System.err.println();     System.err.println("Usage: java free.util.Bounce localPort hostname remotePort [shouldLog]");     System.out.println();     System.out.println("Version 1.01 - 31 Nov. 2002");   } } /**  * The utillib library.  * More information is available at http://www.jinchess.com/.  * Copyright (C) 2002 Alexander Maryanovsky.  * All rights reserved.  *  * The utillib library is free software; you can redistribute  * it and/or modify it under the terms of the GNU Lesser General Public License  * as published by the Free Software Foundation; either version 2 of the  * License, or (at your option) any later version.  *  * The utillib library 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 Lesser  * General Public License for more details.  *  * You should have received a copy of the GNU Lesser General Public License  * along with utillib library; if not, write to the Free Software  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA  */ /**  * An <code>OutputStream</code> which relays all data written into it into a  * list of given <code>OutputStreams</code>.  */ class MultiOutputStream extends OutputStream{   /**    * An array containing the OutputStreams we're relaying data to.    */   private final OutputStream [] streams;   /**    * Creates a new <code>MultiOutputStream</code> which relays data to the    * specified two <code>OutputStreams</code>. Any <code>null</code> values    * will be silently ignored.    */   public MultiOutputStream(OutputStream out1, OutputStream out2){     this(new OutputStream[]{out1, out2});   }   /**    * Creates a new <code>MultiOutputStream</code> which relays data to the    * specified <code>OutputStreams</code>. Any <code>null</code> items in the    * array will be silently ignored.    */   public MultiOutputStream(OutputStream [] streams){     if (streams == null)       throw new IllegalArgumentException("Specified array may not be null");     int count = 0;     for (int i = 0; i < streams.length; i++)       if (streams[i] != null)         count++;     this.streams = new OutputStream[count];     count = 0;     for (int i = 0; i < streams.length; i++){       OutputStream stream = streams[i];       if (stream != null)         this.streams[count++] = stream;     }   }   /**    * Closes all the underlying <code>OutputStreams</code>.    */   public void close() throws IOException{     for (int i = 0; i < streams.length; i++)       streams[i].close();   }   /**    * Flushes all the underlying <code>OutputStreams</code>.    */   public void flush() throws IOException{     for (int i = 0; i < streams.length; i++)       streams[i].flush();   }   /**    * Writes the specified <code>byte</code> into the underlying    * <code>OutputStreams</code>.    */      public void write(int b) throws IOException{     for (int i = 0; i < streams.length; i++)       streams[i].write(b);   }   /**    * Writes the specified amount of bytes from the given byte array starting    * at the specified offset to the underlying <code>OutputStreams</code>.    */   public void write(byte [] arr, int offset, int length) throws IOException{     for (int i = 0; i < streams.length; i++)       streams[i].write(arr, offset, length);   } } /**  * The utillib library.  * More information is available at http://www.jinchess.com/.  * Copyright (C) 2002 Alexander Maryanovsky.  * All rights reserved.  *  * The utillib library is free software; you can redistribute  * it and/or modify it under the terms of the GNU Lesser General Public License  * as published by the Free Software Foundation; either version 2 of the  * License, or (at your option) any later version.  *  * The utillib library 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 Lesser  * General Public License for more details.  *  * You should have received a copy of the GNU Lesser General Public License  * along with utillib library; if not, write to the Free Software  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA  */ /**  * A thread which pumps information read from a given input stream into the  * given output stream.  */  class PumpThread extends Thread{   /**    * The InputStream.    */   private final InputStream in;   /**    * The OutputStream.    */   private final OutputStream out;   /**    * The buffer we're using.    */   private final byte [] buffer;   /**    * The IOException thrown while reading or writing information, or null if    * none.    */   private IOException exception;   /**    * Creates a new PumpThread which will pump information from the given    * InputStream into the given OutputStream.    */   public PumpThread(InputStream in, OutputStream out){     this(in, out, 2048);   }   /**    * Creates a new PumpThread which will pump information from the given    * InputStream into the given OutputStream and will use a buffer of the given    * size.    */   public PumpThread(InputStream in, OutputStream out, int bufSize){     this(in, out, new byte[bufSize]);   }   /**    * Creates a new PumpThread which will pump information from the given    * InputStream into the given OutputStream and will use the given buffer.    */   public PumpThread(InputStream in, OutputStream out, byte [] buffer){     this.in = in;     this.out = out;     this.buffer = buffer;   }   /**    * Does the actual pumping.    */   public void run(){     try{       while (true){         int count = in.read(buffer);         if (count <= 0)           return;         out.write(buffer, 0, count);       }     } catch (IOException e){         exception = e;       }   }   /**    * Returns the exception thrown while reading or writing, or <code>null</code>    * if it finished normally, without throwing an exception (read returned -1).    *    * @throws IllegalStateException if the thread is still alive.    */   public IOException getException(){     if (isAlive())       throw new IllegalStateException("The thread is still alive");     return exception;   } }