/Users/lyon/j4p/src/net/web/PortMap.java

1    /** 
2     * Created by IntelliJ IDEA. 
3     * User: dlyon 
4     * Date: Nov 19, 2003 
5     * Time: 1:16:43 PM 
6     * To change this template use Options | File Templates. 
7     */ 
8    package net.web; 
9     
10   // 
11   // Genaral puporse IP:port forwarder device 
12   // (c) RJHM van den Bergh/comweb.nl 
13   // support@comweb.nl 
14   // 
15   // DISCLAIMER: The use of this software is at your own risk. 
16   // 
17   // Purpose to change it later to a conditonal tunneling device 
18   // I've configured a local http server to listen to port 80 except on one IP address. 
19   // I run this port forwarding device on this IP address. 
20   // So for the browser it just looks if he connects to this http server. 
21   // 
22   // Later on I can add some heuristic algoritme to determine so an applet can request a http tunnel. 
23   // For example a chat applet. 
24   // This way it can bypass proxy firewalls. 
25   // 
26   // COPYRIGHT: 
27   // Freeware but at own risk. 
28   // 
29    
30   import java.io.IOException; 
31   import java.io.InputStream; 
32   import java.io.InterruptedIOException; 
33   import java.io.OutputStream; 
34   import java.net.InetAddress; 
35   import java.net.ServerSocket; 
36   import java.net.Socket; 
37    
38   public class PortMap implements Runnable { 
39       private static Thread serverSocketThread; 
40       // main thread (for ServerSocket) 
41       private Thread serverListenerThread; 
42       private Thread clientListenerThread; 
43       // threads used to handle seperate connections 
44       private Socket clientSocket; 
45       // socket to the client 
46       private Socket serverSocket; 
47       // socket to the server 
48       private InputStream clientInputStream; 
49       // Data from the client 
50       private InputStream serverInputStream; 
51       // Data from the server 
52       private OutputStream clientOutputStream; 
53       // Data to the client; 
54       private OutputStream serverOutputStream; 
55       // Data to the server; 
56       private boolean connectionErrorFlag = false; 
57       // flag indicating that a (connection) error occured 
58       private static final int S0_TIMEOUT = 25000; 
59       // timout 25 seconds, if nothing heard for 25 second 
60       //then the connection is considered lost 
61    
62       private String client_line = ""; 
63       // for debuging 
64    
65       private static ServerSocket mainSocket; 
66       // main socket for new connections 
67       private static final int BACKLOG = 15; 
68       // Max number of waiting connections 
69    
70       private static final int OUT_PORT 
71               = 8086; 
72       // sends output to port 80 
73       private static final String OUTPUT_ADDRESS_STRING 
74               = "show.docjava.com"; 
75       // to localhost 
76    
77       private static final int INPUT_PORT = 80; 
78       // listens to port 80 
79    
80       private static final String INPUT_ADDRESS_STRING 
81               = "localhost"; 
82       // listens on this this IP 
83       private static InetAddress in_address; 
84       // filled in later with the above IP 
85    
86       public PortMap() { 
87           super(); 
88    
89           // create blanc object 
90           serverSocketThread = new Thread(this); 
91           // create main thread 
92           serverSocketThread.start(); 
93           // start main thread (listen for new connections) 
94       } 
95    
96       public PortMap(Socket socket) throws IOException { 
97           clientSocket = socket; 
98           // store socket 
99           clientSocket.setSoTimeout(S0_TIMEOUT); 
100          // set timeout to prevent connections clogging up the server 
101          clientInputStream = clientSocket.getInputStream(); 
102          // get the stream from the client 
103          clientOutputStream = clientSocket.getOutputStream(); 
104          // get the stream to the client 
105   
106          serverSocket = new Socket( 
107                  InetAddress.getByName(OUTPUT_ADDRESS_STRING), 
108                  OUT_PORT); 
109          // create socket to the server 
110          serverSocket.setSoTimeout(S0_TIMEOUT); 
111          // set timeout to prevent connections clogging up 
112          //the server 
113          serverInputStream = serverSocket.getInputStream(); 
114          // get the stream from the server 
115          serverOutputStream = serverSocket.getOutputStream(); 
116          // get the stream to the server 
117   
118          clientListenerThread = new Thread(this); 
119          // create thread that handles client data 
120          serverListenerThread = new Thread(this); 
121          // create thread that handles server data 
122          clientListenerThread.start(); 
123          // start client thread 
124          serverListenerThread.start(); 
125          // start server thread 
126      } 
127   
128      public static void main(String arg[]) { 
129          try { 
130              net.proxy.Proxy.setSoeProxy(); 
131              in_address = InetAddress.getByName(INPUT_ADDRESS_STRING);           // fill in the IP number where to listen to. 
132              mainSocket = new ServerSocket(INPUT_PORT, BACKLOG, in_address);   // create the server socket 
133              new PortMap();                                          // create (and start) the porter application 
134          } catch (Exception e) { 
135              System.out.println("Oops couldnt start");               // Perhaps a bind exception if IP:port already in use. 
136              e.printStackTrace();                                    // print some more debuging information. 
137          } 
138      } 
139   
140      public void run() { 
141          while (Thread.currentThread() == serverSocketThread)            // loop the main thread for ever (if it is the main thread) 
142          { 
143              try { 
144                  new PortMap(mainSocket.accept());           // wait for incomming connections and then start an new porter object (with its own threads) to handle the connection further 
145              } catch (Exception e) { 
146                  System.out.println("Oops error.");      // unwanted error, perhaps caused by the client. 
147                  e.printStackTrace();                    // print more debugging information 
148              } 
149              Thread.yield();                             // always yield at a while loop so it can't consume all processor power 
150          } 
151   
152          while (Thread.currentThread() == clientListenerThread) // if its the thread listening to a client the loop it 
153          { 
154              byte[] data = new byte[1]; 
155              try { 
156                  data[0] = (byte) clientInputStream.read(); 
157   
158  /* 
159  // 
160  // Conditional forwarding can be added here 
161  // It can be done with some heuristic algorithm 
162  // 
163  */ 
164   
165  /* 
166  // 
167  // To output client data to the console 
168  // Note this enormously slows down the forwarding !! 
169  // 
170  if (data[0]!=10) // \n in default encoding 
171  { 
172      client_line=client_line+new String(data); 
173  } else 
174  { 
175      System.out.println("Client: "+client_line); 
176      client_line=""; 
177  } 
178  // 
179  // or easier System.out.write(data[0]); 
180  // 
181  */ 
182   
183                  serverOutputStream.write(data[0]); 
184  // forward the data to the server 
185              } catch (InterruptedIOException ie) 
186  // catch a timeout exception on the client side 
187              { 
188                  System.out.println("Client time out!!"); 
189  // says enough I think, not that this will not be uncommen 
190                  connectionErrorFlag = true; 
191  // set flag to indicate that an error occured 
192              } catch (Exception e) { 
193                  System.out.println("Oops Error client_listener");   // Catch any other error 
194                  e.printStackTrace();                                // output additional debuging info but note that this error is most likely related to some network thing so not very uncommen 
195                  connectionErrorFlag = true;                                 // set error flag so we know forwardign isn't usefull anymore. 
196              } finally { 
197                  Thread.yield();                                     // always yield a while loop so it never consumes all processor power 
198                  if (connectionErrorFlag) { 
199                      close(); 
200                      return; 
201                  } 
202   // check for error and if needed call the close() method of this class instance 
203              } 
204          } 
205   
206          while (Thread.currentThread() == serverListenerThread) 
207                  // if it is the thread listening the server then loop it 
208          { 
209              byte data; 
210              // variable to store data into (byte data) 
211              try { 
212                  data = (byte) serverInputStream.read(); 
213                  // get (response) data from the server 
214                  clientOutputStream.write(data); 
215                  // forward it to the client 
216              } catch (InterruptedIOException ie) 
217   
218  // catch any timeouts from the server 
219  //(prevents server from being clogged with unused connections) 
220              { 
221                  System.out.println("Server time out!!");            // says enough 
222                  connectionErrorFlag = true;                                 // set error flag to indicate that forwarding isn't useful anymore 
223              } catch (Exception e) { 
224                  System.out.println("Oops Error Server_listener");   // Says enough some error occured which isn't uncommen esspecially when its an IO erro 
225                  e.printStackTrace();                                // output additional debugging information 
226                  connectionErrorFlag = true;                                 // set error flag 
227              } finally { 
228                  Thread.yield();                                     // allways yield a while loop, to prevent it using up all processor power 
229                  if (connectionErrorFlag) { 
230                      close(); 
231                      return; 
232                  }               // if an error has ocurred call the close() method from this class instance 
233              } 
234          } 
235      } 
236   
237      private void close() { 
238          try { 
239              if (clientInputStream != null)                                  // check if the stream coming from the the client does exist 
240                  closeStreamFromClient(); 
241          } catch (IOException e) { 
242              System.out.println("Couldn't close stream from client");    // Wierd thing the stream wouldn't close. 
243              e.printStackTrace();                                        // output additional debugging info 
244          } 
245   
246          try { 
247              if (serverInputStream != null)                                      // check if the stream coming from the server exist 
248                  closeStreamToServer(); 
249          } catch (IOException e) { 
250              System.out.println("Couldnt close stream to server");       // Wierd thing, the stream wouldn't close 
251              e.printStackTrace();                                        // output additional debuging information. 
252          } 
253   
254          try { 
255              if (clientSocket != null)                                   // check if the socket to the client exist 
256                  closeSocketToClient(); 
257          } catch (IOException e) { 
258              System.out.println("Couldn't close socket to client.");     // A wierd error occured we couldn't close the socket to the client 
259              e.printStackTrace();                                        // Output additonal debugging information. 
260          } 
261   
262          try { 
263              closeSocketToServer(); 
264          } catch (IOException e) { 
265              System.out.println("Couldn't close socket to server.");     // Wierd couldn't close the socket to the server 
266              e.printStackTrace();                                        // Output additional debugging information 
267          } 
268      } 
269   
270      private void closeSocketToServer() throws IOException { 
271          if (serverSocket != null) {                             // check if the server socket does exist 
272              System.out.println("Closing socket to server.");        // Say that we are going to close the socket to the server 
273              serverSocket.close();                                   // close the socket to the server 
274          } 
275      } 
276   
277      private void closeSocketToClient() throws IOException { 
278          System.out.println("Closing socket to client.");        // say that we are going to close the socket to the client 
279          clientSocket.close();                                   // close the socket to the client. 
280      } 
281   
282      private void closeStreamToServer() throws IOException { 
283          System.out.println("Closing stream to server.");        // Say that we are going to close the stream to the server. 
284          serverInputStream.close();                                      // close the stream coming from the server 
285          clientOutputStream.flush();                                     // Send any pending data from the client to the server 
286      } 
287   
288      private void closeStreamFromClient() throws IOException { 
289          System.out.println("Closing stream from client.");  // sya that we are going to close the stream from the client 
290          clientInputStream.close();                                  // closing the the stream from the client first. 
291          serverOutputStream.flush();                                 // Send any pending data that should go out to the server 
292      } 
293  } 
294