001: /* Copyright 2004 Inderjeet Singh. All rights reserved. You may not modify,
002: * use, reproduce or distribute this software except in compliance with the
003: * terms of the license at http://tcpmon.dev.java.net/
004: * $Id: Tunnel.java,v 1.4 2004/11/09 20:32:15 inder Exp $ */
005:
006: package tcpmon;
007:
008: import java.net.*;
009: import java.io.*;
010:
011: /**
012: * @author Inderjeet Singh
013: */
014: public final class Tunnel extends Thread {
015: /** One of the possible states of the tunnel */
016: public static final String FAILED = "Failed";
017: public static final String CONNNECTED = "Connected";
018: /** One of the possible states of the tunnel */
019: public static final String FINISHED = "Finished";
020:
021: public Tunnel(TunnelConfig config, CallBack callback) {
022: super ("tunnel-" + Debug.getUniqueId());
023: this .config = config;
024: this .callback = callback;
025: this .start();
026: }
027:
028: public void run() {
029: if (!config.startTunnel)
030: return;
031: Socket client = null;
032: try {
033: ServerSocket server = new ServerSocket(config.localPort,
034: MaxBackLog);
035: while (!stopNow) {
036: client = server.accept();
037: (new ConnectionHandler(client)).start();
038: }
039: } catch (IOException ioe) {
040: String clientName = "";
041: if (client != null) {
042: clientName = client.getInetAddress().getHostName();
043: }
044: reportException(ioe, clientName);
045: }
046: }
047:
048: private void reportException(Exception e, String clientName) {
049: String stackTrace = Utils.extractStackTrace(e);
050: CallBack.CallBackData callbackdata = new CallBack.CallBackData(
051: config.localPort, clientName, config.serverName);
052: callbackdata.set(stackTrace, "");
053: callbackdata.setState(FAILED);
054: callback.connectionFinished(callbackdata);
055: }
056:
057: public void stopNow() {
058: stopNow = true;
059: }
060:
061: private boolean stopNow = false;
062:
063: public String toString() {
064: return "(" + config.localPort + ", " + config.serverName + ":"
065: + config.serverPort + ")";
066: }
067:
068: private TunnelConfig config;
069: private CallBack callback;
070: private static final int MaxBackLog = 5;
071:
072: private final class ConnectionHandler extends Thread {
073: ConnectionHandler(Socket client) {
074: super ("conn-" + Debug.getUniqueId());
075: this .client = client;
076: }
077:
078: public void run() {
079: Socket server = null;
080: InetAddress clientAddr = client.getInetAddress();
081: CallBack.CallBackData callbackdata = new CallBack.CallBackData(
082: config.localPort, clientAddr.getHostName(),
083: config.serverName);
084: ByteArrayOutputStream forwardData = new ByteArrayOutputStream();
085: ByteArrayOutputStream reverseData = new ByteArrayOutputStream();
086: try {
087: if (Debug.level >= Debug.MIN_DEBUG)
088: Debug.println("Starting connection thread for "
089: + Tunnel.this .getName() + " ...");
090: if (Debug.level >= Debug.FULL_DEBUG)
091: Debug.println("Connecting " + Tunnel.this + "...");
092: server = new Socket(config.serverName,
093: config.serverPort);
094:
095: // TBD: Reuse the current thread to run one of the streams
096: OutputStream[] fdst = new OutputStream[2];
097: fdst[0] = server.getOutputStream();
098: fdst[1] = forwardData;
099: Thread forward = new StreamThread(client
100: .getInputStream(), fdst);
101: forward.start();
102:
103: // Run the reverse stream in its own thread
104: OutputStream[] rdst = new OutputStream[2];
105: rdst[0] = client.getOutputStream();
106: rdst[1] = reverseData;
107: Thread reverse = new StreamThread(server
108: .getInputStream(), rdst);
109: //reverse.start();
110: reverse.run();
111:
112: forward.join();
113: //reverse.join();
114: } catch (Exception e) {
115: e.printStackTrace(new PrintStream(forwardData));
116: try {
117: if (client != null)
118: client.close();
119: } catch (Exception ee) {
120: ee.printStackTrace(new PrintStream(forwardData));
121: }
122: try {
123: if (server != null)
124: server.close();
125: } catch (Exception ee) {
126: ee.printStackTrace(new PrintStream(forwardData));
127: }
128: } finally {
129: if (Debug.level >= Debug.MIN_DEBUG)
130: Debug.println("Ending connection thread for "
131: + Tunnel.this .getName() + " ...");
132: callbackdata.set(forwardData.toString(), reverseData
133: .toString());
134: callbackdata.setState(FINISHED);
135: callback.connectionFinished(callbackdata);
136: }
137: }
138:
139: private Socket client;
140: }
141: }
|