www.pudn.com > encryption.rar > proxy.java


package encryption;

/**
 * proxy -- a proxy server for telnet
 * --
 * $Id: proxy.java,v 1.4 1997/05/27 13:09:46 leo Exp $
 * $timestamp: Tue May 27 15:08:19 1997 by Matthias L. Jugel :$
 *
 * This 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, or (at your option)
 * any later version.
 *
 * "The Java Telnet Applet" 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 software; see the file COPYING.  If not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.

***********************************************************************
MODIFIED BY CHRISTOFOROS PIRILLOS - MARCH 1999
Modified so it can redirect encrypted communication streams.

The original proxy takes as input 2 ports, establishes connection to
both, creates i/o streams from the sockets and starts the redirection.
I changed it, so it accepts on one side of the connection, a socket, an
input stream and an output stream. So it only has to create the socket 
for the local port. The nature of the i/o streams is totaly transparent to
the proxy server.

 */

import java.net.*;
import java.io.*;
import java.util.*;

/**
 * proxy class -- implements a proxy server to redirect network access
 * @author Matthias L. Jugel, Marcus Meißner, Christoforos Pirillos
 * @version $Id: proxy.java,v 1.4 1997/05/27 13:09:46 leo Exp $
 * Modified to use encrypted streams by Christoforos Pirillos. MARCH 1999
 */

public class proxy implements Runnable
{
  String remoteHost;
  int localPort, remotePort;
  Socket localSocket;
  Thread listener, connection;
//C.Pirillos added this two variables.
  InputStream encryptedInputStream;
  OutputStream encryptedOutputStream;

  /**
   * Initialize the proxy 
   * @param lport local port
   * @param raddr address of the destination
   * @param rport port on the destination host
   * @param in    Encrypted InputStream
   * @param out   Encrypted OutputStream
   * @param s     local Socket
   */

//C.Pirillos
//changed this method to accept an InputStream, an OutputStream and a
//Socket

public proxy(int lport, String raddr, int rport,
 		String name, InputStream in, OutputStream out, Socket s)
  {
    localPort = lport;
    remoteHost = raddr; 
    remotePort = rport;

//C.Pirillos
//added the next 3 lines
    localSocket = s;
    encryptedInputStream=in;
    encryptedOutputStream=out;

    log("destination host is "+remoteHost+" at port "+remotePort);
    log("listening on port "+localPort);

    listener = new Thread(this);
    listener.setPriority(Thread.MIN_PRIORITY);
    listener.start();
  }
  
  /**
   * Cycle around until an error occurs and wait for incoming connections.
   * An incoming connection will create two redirectors. One for
   * local-host - destination-host and one for destination-host - local-host.
   */
  public void run()
  {
      log("accepted connection from "+ localSocket);
      try {
        Socket destinationSocket = new Socket(remoteHost, remotePort);
        log("connecting "+ localSocket.getInetAddress().getHostName() +" <-> "+
            destinationSocket.getInetAddress().getHostName());
//C.Pirillos
//Modified the next two lines 
//Original: redirector r1 = new redirector(localSocket,destinationSocket);
//       redirector r2 = new redirector(destinationSocket,localSocket);

//This makes the proxy to redirect the encryptedInputStream to the
//OutputStream extracted from the destinationSocket, and the InputStream
//extracted from the destinationSocket to the encryptedOutputStream.
//Originally, all streams are extracted from the Sockets

        redirector r1 = new redirector(encryptedInputStream, destinationSocket);
        redirector r2 = new redirector(destinationSocket,encryptedOutputStream);

        r1.couple(r2);
        r2.couple(r1);
      } catch(Exception e) {
	e.printStackTrace();
        System.err.println("proxy: error: cannot create sockets");
        try {
          DataOutputStream os = new DataOutputStream(encryptedOutputStream);
          os.writeChars("Remote host refused connection.\n");
          localSocket.close();
        } catch(IOException ioe) { ioe.printStackTrace(); }
      }
  }

  private void log(String msg)
  {
    System.out.println("proxy: ["+new Date()+"] "+msg);
  }
}

/**
 * A class useful for the proxy server.
 * This class takes over control of newly created connections and redirects
 * the data streams.
 */
class redirector implements Runnable
{
  private redirector companion = null;
  private Socket localSocket;
  private InputStream from;
  private OutputStream to;
  private byte[] buffer = new byte[4096];
  
  /**
   * redirector gets the streams from sockets
   */

//C.Pirillos
//Originally there was only one redirector method.
//Since I have changed the signature of the method, it can't be used
//symmetricaly anymore, so I have to overload it.
//Originally this method took two Sockets as input. 

  public redirector(InputStream in, Socket remote)
  {
    try {
      localSocket = remote;
      from=in; 
      to = localSocket.getOutputStream();
    } catch(Exception e) {
      System.err.println("redirector: cannot get streams");
    }
  }
  public redirector(Socket local, OutputStream out)
  {
    try {
      localSocket = local; 
      from = localSocket.getInputStream();
      to = out; 
    } catch(Exception e) {
      System.err.println("redirector: cannot get streams");
    }
  }

  /**
   * couple this redirector instance with another one (usually the other
   * direction of the connection)
   */
  public void couple(redirector c) { 
    companion = c; 
    Thread listen = new Thread(this);
    listen.start();
  }

  /**
   * decouple us from our companion. This will let this redirector die after
   * exiting from run()
   */
  public void decouple() { companion = null; }

  /**
   * read data from the input and write it to the destination stream until
   * an error occurs or our companion is decoupled from us
   */
  public void run()
  {
    int count;
    try {
      while(companion != null) {
        if((count = from.read(buffer)) < 0)
          break;
        to.write(buffer, 0, count);
//C.Pirillos
//For some reason when using the encrypted streams, you have to implicitly
//flush the outputStream

	to.flush();
	 }
    } catch(Exception e) {
      System.err.println("redirector: connection lost");
    }
    try {
      from.close();
      to.close();
     localSocket.close();

      // is our companion dead? no, then decouple, because we die
      if(companion != null) companion.decouple();
    } catch(Exception io) {
      System.err.println("redirector: error closing streams and sockets");
      io.printStackTrace();
    }
  }
}