Source Code for:
"JTRouter: Let Your Clients Tunnel Their Way Across the Internet," Vol. 2, Issue 10, p. 8

 
Listing 1: pipedSocketStream.java.
import java.net.Socket;
import java.io.*;
public class PipedSocketStream
    implements Runnable {
  private int ch;
  private DataInputStream dis;
  private DataOutputStream dos;

  public PipedSocketStream(Socket s1,
                           Socket s2) {
    try {
      dis =
        new DataInputStream(s1.getInputStream());
      dos =
        new DataOutputStream(s2.getOutputStream());
    }
    catch(IOException ioe) {
      ioe.printStackTrace();
      System.exit(1);
    }
  } // End PipedSocketStream() constructor

  public void run() {
    // Read and write from piped sockets
    while(true) {
      try {
        if (!this.readAndWrite())
          return;
      }
      catch (IOException e) {
        return;
      }
    }
  }  // End run() method

  private synchronized boolean readAndWrite()
      throws IOException {
    if ((ch = dis.read()) < 0)
      return false;
    dos.write(ch);
    dos.flush();
    return true;
  } // End readAndWrite() method
} // End Class PipedSocketStream

Listing 2: jtunnel.java.
import java.net.*;
import java.io.*;
import java.lang.Thread;

public class JTunnel {
  public Socket cSocket;
  public Socket sSocket;
  private Thread clientServerPipe;
  private Thread serverClientPipe;

  public JTunnel(Socket in_cSocket,
                 Socket in_sSocket) {
    cSocket = in_cSocket;
    sSocket = in_sSocket;
  } // End JTunnel constructor

  // Create and activate PipedSocketStreams
  public void JTopen() {
    clientServerPipe =
      new Thread(new PipedSocketStream(cSocket,
                                       sSocket));
    serverClientPipe =
      new Thread(new PipedSocketStream(sSocket,
                                       cSocket));
    System.out.println("Starting socket pipes");
    clientServerPipe.start();
    serverClientPipe.start();
  } // End openJT() method

  public boolean isActive() {
    if (clientServerPipe.isAlive() &&
        serverClientPipe.isAlive())
      return true;
    return false;
  } // End isActive() method

  public void JTclose() {
    if (clientServerPipe.isAlive())
      clientServerPipe.stop();
    if (serverClientPipe.isAlive())
      serverClientPipe.stop();

    try {
      if (cSocket != null)
          cSocket.close();
      if (sSocket != null)
          sSocket.close();
    }
    catch (IOException ioe) {
      ioe.printStackTrace();
    }
  } // End closeJT() method

  public void finalize()
  {
    JTclose();
  } // End finalize() method
} // End class JTunnel

Listing 3: jtserver.java.
import java.util.*;
import java.lang.*;
import java.io.*;
import java.net.*;

class JTServer implements Runnable{
  public int clientPort = 0;
  private int remoteHostPort = 0;
  private String remoteHostAddr = null;

  private Vector jTunnels = new Vector();
  public Vector jtPending = new Vector();
  public int activeConnections = 0;
  public boolean jtChanged = true;

  public static void main(String[] args) {
    int in_clientPort = 0;
    int in_remoteHostPort = 0;
    String in_remoteHostAddr = null;
    DataInputStream dis =
           new DataInputStream(System.in);

    try {
      System.out.println("Caller port: ");
      in_clientPort =
            Integer.parseInt(dis.readLine());
      System.out.println("Remote Host Port: ");
      in_remoteHostPort =
            Integer.parseInt(dis.readLine());
      System.out.println("Remote Host Address:");
      in_remoteHostAddr = dis.readLine();
    }
    catch (IOException ioe) {
      ioe.printStackTrace();
      System.exit(1);
    }
    // Create and start JTServer thread
    Thread jts = new Thread (
      new JTServer(in_clientPort,
        in_remoteHostPort, in_remoteHostAddr));
    jts.run();
  } // End main()

  public JTServer(int in_clientPort,
                  int in_remoteHostPort,
                  String in_remoteHostAddr) {
    clientPort = in_clientPort;
    remoteHostPort = in_remoteHostPort;
    remoteHostAddr = in_remoteHostAddr;
  }

  public synchronized void run() {
    Thread jtListener =
      new Thread(new JTListener(this));
    jtListener.start();
    jtChanged = false;

    while (true) {
      try {
        this.wait(100);
      }
      catch (InterruptedException ie) {
        ie.printStackTrace();
      }

      // Clear JTunnels with dead threads
      processQueuedConnections();
      cleanJTunnels();
      if (jtChanged) {
        System.out.println("No. of JTunnels = " +
                           activeConnections);
        jtChanged = false;
      }
    } // End while loop
  } // End run() method

  void processQueuedConnections() {
    Vector newJTunnels = new Vector();
    if (jtPending.size() == 0)
      return;

    synchronized (jtPending) {
      for (int i = 0;
        i < jtPending.size(); i++) {
           newJTunnels.addElement((Socket)
             (jtPending.elementAt(i)));
      }
      // Clear the JTunnels Pending queue
      jtPending.removeAllElements();
    }
    for (int i = 0; i < newJTunnels.size(); i++) {
      Socket clientSocket =
           (Socket)(newJTunnels.elementAt(i));

      // connect to remoteHost
      Socket remoteHostSocket = connectToRemoteHost();
      if (remoteHostSocket == null)
        continue;

      // Create New JTunnel; add it to JTunnels
      JTunnel jTunnel = null;
      try {
          jTunnel = new JTunnel(clientSocket,
                                remoteHostSocket);
          jTunnel.JTopen();
      }
      catch(Exception e) {
        e.printStackTrace();
        System.exit(1);
      }
      jTunnels.addElement(jTunnel);
      activeConnections++;
      jtChanged = true;
    } // End for loop
   } // End processQueuedConnections() method

  // Try to connect to the remote host
  public Socket connectToRemoteHost() {
    Socket sock;
    try {
      sock = new Socket(remoteHostAddr,
                        remoteHostPort);
    }
    catch(IOException ioe) {
      ioe.printStackTrace();
      return null;
    }
    return sock;
  } // End method connectToRemtoeHost()

  // Close JTunnels associated with dead threads
  void cleanJTunnels() {
    for (int i = 0; i < jTunnels.size(); i++) {
      JTunnel jTunnel =
             (JTunnel)(jTunnels.elementAt(i));
      if (!(jTunnel.isActive())) {
        jTunnel.JTclose();
        jTunnels.removeElementAt(i);
        jtChanged = true;
        activeConnections--;
      }
    }
  } // End checkJTunnels() method
} //End Class JTServer

Listing 4: JTListener.java.
import java.io.*;
import java.net.*;
import java.lang.Thread;

class JTListener implements Runnable {
  private JTServer jts;
  private ServerSocket jtServerSocket = null;

  public JTListener(JTServer in_jts) {
    jts = in_jts;
    try {
      jtServerSocket =
          new ServerSocket(jts.clientPort);
      System.out.println("Server started on port "
                         + jts.clientPort);
    }
    catch(IOException ioe) {
      ioe.printStackTrace();
      System.exit(2);
    }
  } // end method createJTServerSocket

  public void run() {
    while (true) {
      System.out.println("Accepting connections");
      try {
        Thread.sleep(100);
      }
      catch (InterruptedException ie) {
        break;
      }

      // Accept internet connection requests
      Socket clientSocket;
      if ((clientSocket = acceptConnection())
                                    == null) {
        System.out.println("Got null socket");
        System.exit(1);
      }
      System.out.println("Got request, " +
      "clientSocket = " + clientSocket);
      synchronized(jts.jtPending) {
        jts.jtPending.addElement(clientSocket);
      }
      synchronized(jts) {
        jts.notify();
      }
    } // End while loop
  } // End run() method

  // accept client connections
  private Socket acceptConnection() {
    Socket sock = null;
    try {
      sock = jtServerSocket.accept();
      System.out.println("Connection from: " +
              sock.getInetAddress().toString());
    }
    catch(Exception e) {
      e.printStackTrace();
      System.exit(4);
    }
    return sock;
  } // End method acceptConnection()
} // End Class JTListener