(no commit message)
authorErik Brakkee <erik@brakkee.org>
Thu, 16 Mar 2006 18:59:11 +0000 (18:59 +0000)
committerErik Brakkee <erik@brakkee.org>
Thu, 16 Mar 2006 18:59:11 +0000 (18:59 +0000)
socketproxy/build.xml [new file with mode: 0644]
socketproxy/src/org/wamblee/socketproxy/Barrier.java [new file with mode: 0644]
socketproxy/src/org/wamblee/socketproxy/ForwarderThread.java [new file with mode: 0644]
socketproxy/src/org/wamblee/socketproxy/SocketProxy.java [new file with mode: 0644]

diff --git a/socketproxy/build.xml b/socketproxy/build.xml
new file mode 100644 (file)
index 0000000..ec298d3
--- /dev/null
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+
+<!DOCTYPE project [
+    <!ENTITY header SYSTEM "file:../build/header.xml">
+    <!ENTITY trailer SYSTEM "file:../build/trailer.xml">
+]>
+
+<project name="socketproxy" default="jar" basedir=".">
+
+
+       <!-- =============================================================================== -->
+       <!-- Include the build header defining general properties                            -->
+       <!-- =============================================================================== -->
+    <property name="project.home" value=".."/>
+    <property name="module.name" value="socketproxy" />
+
+   &header;
+       
+       <target name="module.build.deps" 
+         depends="">
+       </target>
+       
+       <!-- Set libraries to use in addition for test, a library which 
+                            is already mentioned in module.build.path should not be 
+                            mentioned below again --> 
+       <target name="module.test.deps" depends="">
+       </target>
+                       
+  &trailer; 
+  
+  
+</project>
diff --git a/socketproxy/src/org/wamblee/socketproxy/Barrier.java b/socketproxy/src/org/wamblee/socketproxy/Barrier.java
new file mode 100644 (file)
index 0000000..e8f9f81
--- /dev/null
@@ -0,0 +1,36 @@
+package org.wamblee.socketproxy; 
+
+/**
+ * Copyright (c) 2005 UPS_SCS NL
+ * 
+ */
+
+public class Barrier {
+
+    private int _countLeft;
+
+    public Barrier( int aCount ) {
+        _countLeft = aCount;
+    }
+
+    public synchronized void block( ) {
+        _countLeft--;
+        if ( _countLeft < 0 ) {
+            throw new IllegalStateException(
+                    "Barrier count became negative, programming error" );
+        }
+        notifyAll( );
+        while ( _countLeft > 0 ) {
+            waitUninterruptable( );
+        }
+    }
+
+    private void waitUninterruptable( ) {
+        try {
+            wait( );
+        } catch ( InterruptedException e ) {
+            // ignore.
+        }
+    }
+
+}
diff --git a/socketproxy/src/org/wamblee/socketproxy/ForwarderThread.java b/socketproxy/src/org/wamblee/socketproxy/ForwarderThread.java
new file mode 100644 (file)
index 0000000..53988b1
--- /dev/null
@@ -0,0 +1,86 @@
+package org.wamblee.socketproxy;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * Forwarder thread which handles forwarding of an input stream to
+ * an output stream. 
+ */
+
+public class ForwarderThread extends Thread {
+
+    private String _prefix;
+
+    private Barrier _barrier;
+
+    private InputStream _is;
+
+    private OutputStream _os;
+
+    /**
+     * Constructs the forwarder thread.
+     * @param aPrefix Prefix to use in the output. 
+     * @param aBarrier Barrier to block on before actually closing the stream. 
+     *        This is done to make sure that connections are only closed in th e
+     *        proxy when the forwarders in both directions are ready to close. 
+     * @param aIs Input stream to read from.
+     * @param aOs Output stream to forward to.
+     */
+    public ForwarderThread( String aPrefix, Barrier aBarrier,
+            InputStream aIs, OutputStream aOs ) {
+        _prefix = aPrefix;
+        _is = aIs;
+        _os = aOs;
+        _barrier = aBarrier;
+    }
+
+    public void run( ) {
+        boolean firstChar = true;
+        try {
+            int c = _is.read( );
+            while ( c > 0 ) {
+                try {
+                    _os.write( c );
+                    _os.flush( );
+                    if ( firstChar ) {
+                        System.out.print( _prefix );
+                        firstChar = false;
+                    }
+                    System.out.print( (char) c );
+                    if ( c == '\n' ) {
+                        firstChar = true;
+                    }
+                } catch ( IOException e ) {
+                }
+
+                c = _is.read( );
+            }
+        } catch ( IOException e ) {
+        }
+        closeStreams();
+    }
+
+    /**
+     * @param is
+     * @param os
+     */
+    private void closeStreams( ) {
+        _barrier.block( ); // wait until the other forwarder for the other direction
+                           // is also closed.
+        try {
+            _is.close( );
+        } catch ( IOException e1 ) {
+            // Empty.
+        }
+        try {
+            _os.flush( );
+            _os.close( );
+        } catch ( IOException e1 ) {
+            // Empty
+        }
+        System.out.println(_prefix + " closed");
+    }
+
+}
diff --git a/socketproxy/src/org/wamblee/socketproxy/SocketProxy.java b/socketproxy/src/org/wamblee/socketproxy/SocketProxy.java
new file mode 100644 (file)
index 0000000..25d350f
--- /dev/null
@@ -0,0 +1,101 @@
+package org.wamblee.socketproxy;
+
+/*
+ * Created on Apr 5, 2005
+ */
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.ServerSocket;
+import java.net.Socket;
+
+/**
+ * @author erik
+ * 
+ * TODO To change the template for this generated type comment go to Window -
+ * Preferences - Java - Code Style - Code Templates
+ */
+public class SocketProxy {
+
+    public static void main( final String[] args ) throws IOException {
+        for ( int i = 0; i < args.length; i++ ) {
+            // System.out.println(i + " " + args[i]);
+            String[] fields = args[i].split( ":" );
+            final int localPort = Integer.parseInt( fields[0] );
+            final String host = fields[1];
+            final int remotePort = Integer.parseInt( fields[2] );
+            runSocketProxy( localPort, host, remotePort );
+        }
+    }
+
+    /**
+     * @param localPort
+     * @param host
+     * @param remotePort
+     */
+    private static void runSocketProxy( final int localPort,
+            final String host, final int remotePort ) {
+        new Thread( new Runnable( ) {
+            public void run( ) {
+                try {
+                    new SocketProxy( localPort, host, remotePort );
+                } catch ( IOException e ) {
+                    System.out.println( "Problem with socket " + localPort
+                            + ":" + host + ":" + remotePort );
+                    e.printStackTrace( );
+                }
+            }
+        } ).start( );
+    }
+
+    public SocketProxy( int localPort, String remoteHost, int remotePort )
+            throws IOException {        
+        System.out.println( "Listening on port " + localPort );
+        ServerSocket server = new ServerSocket( localPort );
+        for ( ;; ) {
+            Socket socket = server.accept( );
+            System.out.println( "Got local connection on port "
+                    + localPort );
+            InputStream localIs = socket.getInputStream( );
+            OutputStream localOs = socket.getOutputStream( );
+            Socket clientSocket = new Socket( remoteHost, remotePort );
+            final String description = "Port forwarding: " + localPort
+                    + " -> " + remoteHost + ":" + remotePort;
+            System.out.println( description + " established." );
+            InputStream serverIs = clientSocket.getInputStream( );
+            OutputStream serverOs = clientSocket.getOutputStream( );
+            Barrier barrier = new Barrier(2);
+            final Thread t1 = runForwarder( barrier, "> ", localIs, serverOs );
+            final Thread t2 = runForwarder( barrier, "< ", serverIs, localOs );
+            waitForConnectionClose( description, t1, t2 );
+        }
+    }
+
+    /**
+     * @param description
+     * @param t1
+     * @param t2
+     */
+    private void waitForConnectionClose( final String description,
+            final Thread t1, final Thread t2 ) {
+        new Thread( new Runnable( ) {
+            public void run( ) {
+                try {
+                    t1.join( );
+                    t2.join( );
+                } catch ( InterruptedException e ) {
+                    e.printStackTrace( );
+                }
+                System.out.println( description + " closed" );
+            }
+        } ).start( );
+    }
+
+    private Thread runForwarder( final Barrier barrier, final String prefix,
+            final InputStream is, final OutputStream os ) {
+        Thread t = new ForwarderThread(prefix, barrier, is, os);
+        t.start( );
+        return t;
+    }
+}