Redirects incoming TCP connections to other hosts/ports : Socket « Network Protocol « Java






Redirects incoming TCP connections to other hosts/ports

     
// $Id: Proxy.java,v 1.3.4.1 2008/01/22 10:01:16 belaban Exp $



import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSocketFactory;
import java.io.*;
import java.net.*;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.*;
import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;


/**
 * Redirects incoming TCP connections to other hosts/ports. All redirections are defined in a file as for example
 * <pre>
 * 127.0.0.1:8888=www.ibm.com:80
 * localhost:80=pop.mail.yahoo.com:110
 * </pre>
 * The first line forwards all requests to port 8888 on to www.ibm.com at port 80 (it also forwards the HTTP
 * response back to the sender. The second line essentially provides a POP-3 service on port 8110, using
 * Yahoo's POP service. This is neat when you're behind a firewall and one of the few services in the outside
 * world that are not blocked is port 80 (HHTP).<br/>
 * Note that JDK 1.4 is required for this class. Also, concurrent.jar has to be on the classpath. Note that
 * you also need to include jsse.jar/jce.jar (same location as rt.jar) if you want SSL sockets.<br>
 * To create SSLServerSockets you'll need to do the following:
 * Generate a certificate as follows:
 * <pre>
 * keytool -genkey -keystore /home/bela/.keystore -keyalg rsa -alias bela -storepass <passwd> -keypass <passwd>
 * </pre>
 *
 * Start the Proxy as follows:
 * <pre>
 * java -Djavax.net.ssl.keyStore=/home/bela/.keystore -Djavax.net.ssl.keyStorePassword=<passwd>
 *      -Djavax.net.ssl.trustStore=/home/bela/.keystore -Djavax.net.ssl.trustStorePassword=<passwd>
 *      org.jgroups.util.Proxy -file /home/bela/map.properties
 * </pre>
 * Start client as follows:
 * <pre>
 * java -Djavax.net.ssl.trustStore=/home/bela/.keystore -Djavax.net.ssl.trustStorePassword=<passwd> sslclient
 * </pre>
 * <br/>
 * To import a certificate into the keystore, use the following steps:
 * <pre>
 * openssl x509 -in server.crt -out server.crt.der -outform DER
 * keytool -import -trustcacerts -alias <your alias name> -file server.crt.der
 * </pre>
 * This will store the server's certificate in the ${user.home}/.keystore key store.
 * <br/>
 * Note that an SSL client or server can be debugged by starting it as follows:
 * <pre>-Djava.protocol.handler.pkgs=com.sun.net.ssl.internal.www.protocol -Djavax.net.debug=ssl</pre>
 * <br/>
 * If you run a web browser, simply enter https://<host>:<port> as URL to connect to an SSLServerSocket
 * <br/>Note that we cannot use JDK 1.4's selectors for SSL sockets, as
 * getChannel() on an SSL socket doesn't seem to work.
 * @todo Check whether SSLSocket.getChannel() or SSLServerSocket.getChannel() works.
 * @author Bela Ban
 */
public class Proxy {
    InetAddress           local=null, remote=null;
    int                   local_port=0, remote_port=0;
    static boolean        verbose=false;
    static boolean        debug=false;
    String                mapping_file=null; // contains a list of src and dest host:port pairs
    final HashMap         mappings=new HashMap(); // keys=MyInetSocketAddr (src), values=MyInetSocketAddr (dest)
    Executor              executor; // maintains a thread pool
    static final int      MIN_THREAD_POOL_SIZE=2;
    static final int      MAX_THREAD_POOL_SIZE=64; // for processing requests
    static final int      BUFSIZE=1024; // size of data transfer buffer



    public Proxy(InetAddress local, int local_port, InetAddress remote, int remote_port, boolean verbose, boolean debug) {
        this.local=local;
        this.local_port=local_port;
        this.remote=remote;
        this.remote_port=remote_port;
        Proxy.verbose=verbose;
        Proxy.debug=debug;
    }

    public Proxy(InetAddress local, int local_port, InetAddress remote, int remote_port,
                    boolean verbose, boolean debug, String mapping_file) {
        this(local, local_port, remote, remote_port, verbose, debug);
        this.mapping_file=mapping_file;
    }

    public void start() throws Exception {
        Map.Entry           entry;
        Selector            selector;
        ServerSocketChannel sock_channel;
        MyInetSocketAddress key, value;

        if (remote !=null && local !=null)
            mappings.put(new InetSocketAddress(local, local_port), new InetSocketAddress(remote, remote_port));
        
        if (mapping_file !=null) {
            try {
                populateMappings(mapping_file);
            }
            catch (Exception ex) {
                log("Failed reading " + mapping_file);
                throw ex;
            }
        }

        log("\nProxy started at " + new java.util.Date());

        if (verbose) {
            log("\nMappings:\n---------");
            for (Iterator it=mappings.entrySet().iterator(); it.hasNext();) {
                entry=(Map.Entry) it.next();
                log(toString((InetSocketAddress) entry.getKey()) + " <--> "
                    + toString((InetSocketAddress) entry.getValue()));
            }
            log("\n");
        }

        // 1. Create a Selector
        selector=Selector.open();

        // Create a thread pool (Executor)
        executor=new ThreadPoolExecutor(MIN_THREAD_POOL_SIZE, MAX_THREAD_POOL_SIZE, 30000, TimeUnit.MILLISECONDS,
                                        new LinkedBlockingQueue(1000));

        for (Iterator it=mappings.keySet().iterator(); it.hasNext();) {
            key=(MyInetSocketAddress) it.next();
            value=(MyInetSocketAddress) mappings.get(key);

            // if either source or destination are SSL, we cannot use JDK 1.4
            // NIO selectors, but have to fall back on separate threads per connection

            if (key.ssl() || value.ssl()) {
                // if(2 == 2) {
                SocketAcceptor acceptor=new SocketAcceptor(key, value);
                executor.execute(acceptor);
                continue;
            }

            // 2. Create a ServerSocketChannel
            sock_channel=ServerSocketChannel.open();
            sock_channel.configureBlocking(false);
            sock_channel.socket().bind(key);

            // 3. Register the selector with all server sockets. 'Key' is attachment, so we get it again on
            //    select(). That way we can associate it with the mappings hashmap to find the corresponding
            //    value
            sock_channel.register(selector, SelectionKey.OP_ACCEPT, key);
        }

        // 4. Start main loop. won't return until CTRL-C'ed        
        loop(selector);
    }



    /** We handle only non-SSL connections */
    void loop(Selector selector) {
        Set                 ready_keys;
        SelectionKey        key;
        ServerSocketChannel srv_sock;
        SocketChannel       in_sock, out_sock;
        InetSocketAddress   src, dest;

        while (true) {
            if (verbose)
                log("[Proxy] ready to accept connection");

            // 4. Call Selector.select()
            try {
                selector.select();

                // get set of ready objects
                ready_keys=selector.selectedKeys();
                for (Iterator it=ready_keys.iterator(); it.hasNext();) {
                    key=(SelectionKey) it.next();
                    it.remove();

                    if (key.isAcceptable()) {
                        srv_sock=(ServerSocketChannel) key.channel();
                        // get server socket and attachment
                        src=(InetSocketAddress) key.attachment();
                        in_sock=srv_sock.accept(); // accept request
                        if (verbose)
                            log("Proxy.loop()", "accepted connection from " + toString(in_sock));
                        dest=(InetSocketAddress) mappings.get(src);
                        // find corresponding dest
                        if (dest == null) {
                            in_sock.close();
                            log("Proxy.loop()", "did not find a destination host for " + src);
                            continue;
                        }
                        else {
                            if (verbose)
                                log("Proxy.loop()", "relaying traffic from " + toString(src) + " to " + toString(dest));
                        }

                        // establish connection to destination host
                        try {
                            out_sock=SocketChannel.open(dest);
                            // uses thread pool (Executor) to handle request, closes socks at end
                            handleConnection(in_sock, out_sock);
                        }
                        catch (Exception ex) {
                            in_sock.close();
                            throw ex;
                        }
                    }
                }
            }
            catch (Exception ex) {
                log("Proxy.loop()", "exception: " + ex);
            }
        }
    }

    //    void handleConnection(Socket in_sock, Socket out_sock) {
    //        try {
    //            Relayer r=new Relayer(in_sock, out_sock);
    //            executor.execute(r);
    //            r=new Relayer(out_sock, in_sock);
    //            executor.execute(r);
    //        }
    //        catch (Exception ex) {
    //            log("Proxy.handleConnection()", "exception: " + ex);
    //        }
    //        finally {
    //            close(in_sock, out_sock);
    //        }
    //    }

    void handleConnection(SocketChannel in, SocketChannel out) {
        try {
            _handleConnection(in, out);
        }
        catch (Exception ex) {
            log("Proxy.handleConnection()", "exception: " + ex);
        }
    }
    
    void _handleConnection(final SocketChannel in_channel, final SocketChannel out_channel) throws Exception {
        executor.execute(new Runnable() {
                public void run() {
                    Selector sel=null;
                    SocketChannel tmp;
                    Set ready_keys;
                    SelectionKey key;
                    ByteBuffer transfer_buf=ByteBuffer.allocate(BUFSIZE);

                    try {
                        sel=Selector.open();
                        in_channel.configureBlocking(false);
                        out_channel.configureBlocking(false);
                        in_channel.register(sel, SelectionKey.OP_READ);
                        out_channel.register(sel, SelectionKey.OP_READ);
                        
                        while (sel.select() > 0) {
                            ready_keys=sel.selectedKeys();
                            for (Iterator it=ready_keys.iterator(); it.hasNext();) {
                                key=(SelectionKey) it.next();
                                it.remove(); // remove current entry (why ?)
                                tmp=(SocketChannel) key.channel();
                                if (tmp == null) {
                                    log(
                                        "Proxy._handleConnection()",
                                        "attachment is null, continuing");
                                    continue;
                                }
                                if (key.isReadable()) { // data is available to be read from tmp
                                    if (tmp == in_channel) {
                                        // read all data from in_channel and forward it to out_channel (request)
                                        if (relay(tmp, out_channel, transfer_buf) == false)
                                            return;
                                    }
                                    if (tmp == out_channel) {
                                        // read all data from out_channel and forward it 
                                        // to in_channel (response)
                                        if (relay(tmp, in_channel, transfer_buf) == false)
                                            return;
                                    }
                                }
                            }
                        }
                    }
                    catch (Exception ex) {
                        ex.printStackTrace();
                    }
                    finally {
                        close(sel, in_channel, out_channel);
                    }
                }
            });
    }
    
    void close(Selector sel, SocketChannel in_channel, SocketChannel out_channel) {
        try {
            if (sel !=null)
                sel.close();
        }
        catch (Exception ex) {
        }
        try {
            if (in_channel !=null)
                in_channel.close();
        }
        catch (Exception ex) {
        }
        try {
            if (out_channel !=null)
                out_channel.close();
        }
        catch (Exception ex) {
        }
    }


    /**
     * Read all data from <code>from</code> and write it to <code>to</code>.
     * Returns false if channel was closed
     */
    boolean relay(SocketChannel from, SocketChannel to, ByteBuffer buf) throws Exception {
        int num;
        StringBuilder sb;

        buf.clear();
        while (true) {
            num=from.read(buf);
            if (num < 0)
                return false;
            else
                if (num == 0)
                    return true;
            buf.flip();
            if (verbose) {
                log(printRelayedData(toString(from), toString(to), buf.remaining()));
            }
            if (debug) {
                sb=new StringBuilder();
                sb.append(new String(buf.array()).trim());
                sb.append('\n');
                log(sb.toString());
            }
            to.write(buf);
            buf.flip();
        }
    }

    String toString(SocketChannel ch) {
        StringBuilder sb=new StringBuilder();
        Socket sock;

        if (ch == null)
            return null;
        if ((sock=ch.socket()) == null)
            return null;
        sb.append(sock.getInetAddress().getHostName()).append(':').append(sock.getPort());
        return sb.toString();
    }

    String toString(InetSocketAddress addr) {
        StringBuilder sb;
        sb=new StringBuilder();

        if (addr == null)
            return null;
        sb.append(addr.getAddress().getHostName()).append(':').append(addr.getPort());
        if (addr instanceof MyInetSocketAddress)
            sb.append(" [ssl=").append(((MyInetSocketAddress) addr).ssl()).append(']');
        return sb.toString();
    }

    
    static String printRelayedData(String from, String to, int num_bytes) {
        StringBuilder sb;
        sb=new StringBuilder();
        sb.append("\n[PROXY] ").append(from);
        sb.append(" to ").append(to);
        sb.append(" (").append(num_bytes).append(" bytes)");
        // log("Proxy.relay()", sb.toString());
        return sb.toString();
    }
    

    /**
     * Populates <code>mappings</code> hashmap. An example of a definition file is:
     * <pre>
     * http://localhost:8888=http://www.yahoo.com:80
     * https://localhost:2200=https://cvs.sourceforge.net:22
     * http://localhost:8000=https://www.ibm.com:443
     * </pre>
     * Mappings can be http-https, https-http, http-http or https-https
     */
    void populateMappings(String filename) throws Exception {
        FileInputStream   in=new FileInputStream(filename);
        BufferedReader    reader;
        String            line;
        URI               key, value;
        int               index;
        boolean           ssl_key, ssl_value;
        final String      HTTPS="https";

        reader=new BufferedReader(new InputStreamReader(in));
        while ((line=reader.readLine()) !=null) {
            line=line.trim();
            if (line.startsWith("//") || line.startsWith("#") || line.length() == 0)
                continue;
            index=line.indexOf('=');
            if (index == -1)
                throw new Exception("Proxy.populateMappings(): detected no '=' character in " + line);
            key=new URI(line.substring(0, index));
            ssl_key=key.getScheme().trim().equals(HTTPS);

            value=new URI(line.substring(index + 1));
            ssl_value=value.getScheme().trim().equals(HTTPS);

            check(key);
            check(value);

            log("key: " + key + ", value: " + value);

            mappings.put(new MyInetSocketAddress(key.getHost(), key.getPort(), ssl_key),
                         new MyInetSocketAddress(value.getHost(), value.getPort(), ssl_value));
        }
        in.close();
    }

    /** Checks whether a URI is http(s)://<host>:<port> */
    void check(URI u) throws Exception {
        if (u.getScheme() == null)
            throw new Exception(
                "scheme is null in " + u + ", (valid URI is \"http(s)://<host>:<port>\")");

        if (u.getHost() == null)
            throw new Exception(
                "host is null in " + u + ", (valid URI is \"http(s)://<host>:<port>\")");

        if (u.getPort() <=0)
            throw new Exception(
                "port is <=0 in " + u + ", (valid URI is \"http(s)://<host>:<port>\")");

    }

    /** Input is "host:port" */
    SocketAddress strToAddr(String input) throws Exception {
        StringTokenizer tok=new StringTokenizer(input, ":");
        String host, port;

        host=tok.nextToken();
        port=tok.nextToken();
        return new InetSocketAddress(host, Integer.parseInt(port));
    }

    String printSelectionOps(SelectionKey key) {
        StringBuilder sb=new StringBuilder();
        if ((key.readyOps() & SelectionKey.OP_ACCEPT) !=0)
            sb.append("OP_ACCEPT ");
        if ((key.readyOps() & SelectionKey.OP_CONNECT) !=0)
            sb.append("OP_CONNECT ");
        if ((key.readyOps() & SelectionKey.OP_READ) !=0)
            sb.append("OP_READ ");
        if ((key.readyOps() & SelectionKey.OP_WRITE) !=0)
            sb.append("OP_WRITE ");
        return sb.toString();
    }

    public static void main(String[] args) {
        Proxy    p;
        InetAddress local=null, remote=null;
        int         local_port=0, remote_port=0;
        String      tmp, tmp_addr, tmp_port;
        boolean     verbose=false, debug=false;
        int         index;
        String      mapping_file=null;

        try {
            for (int i=0; i < args.length; i++) {
                tmp=args[i];
                if ("-help".equals(tmp)) {
                    help();
                    return;
                }
                if ("-verbose".equals(tmp)) {
                    verbose=true;
                    continue;
                }
                if ("-local".equals(tmp)) {
                    tmp_addr=args[++i];
                    index=tmp_addr.indexOf(':');
                    if (index > -1) { // it is in the format address:port
                        tmp_port=tmp_addr.substring(index + 1);
                        local_port=Integer.parseInt(tmp_port);
                        tmp_addr=tmp_addr.substring(0, index);
                        local=InetAddress.getByName(tmp_addr);
                    }
                    else
                        local=InetAddress.getByName(args[++i]);
                    continue;
                }
                if ("-local_port".equals(tmp)) {
                    local_port=Integer.parseInt(args[++i]);
                    continue;
                }
                if ("-remote".equals(tmp)) {
                    tmp_addr=args[++i];
                    index=tmp_addr.indexOf(':');
                    if (index > -1) { // it is in the format address:port
                        tmp_port=tmp_addr.substring(index + 1);
                        remote_port=Integer.parseInt(tmp_port);
                        tmp_addr=tmp_addr.substring(0, index);
                        remote=InetAddress.getByName(tmp_addr);
                    }
                    else
                        remote=InetAddress.getByName(args[++i]);
                    continue;
                }
                if ("-remote_port".equals(tmp)) {
                    remote_port=Integer.parseInt(args[++i]);
                    continue;
                }
                if ("-file".equals(tmp)) {
                    mapping_file=args[++i];
                    continue;
                }
                if ("-debug".equals(tmp)) {
                    debug=true;
                    continue;
                }
                help();
                return;
            }

            if (local == null)
                local=InetAddress.getLocalHost();

            p=new Proxy(local, local_port, remote, remote_port, verbose, debug, mapping_file);
            p.start();
        }
        catch (Throwable ex) {
            ex.printStackTrace();
        }
    }

    static void help() {
        System.out.println("Proxy [-help] [-local <local address>] [-local_port <port>] "
                           + "[-remote <remote address>] [-remote_port <port>] [-verbose] "
                           + "[-file <mapping file>] [-debug]");
    }

    static void log(String method_name, String msg) {
        System.out.println('[' + method_name + "]: " + msg);
    }

    static void log(String msg) {
        System.out.println(msg);
    }

    static void close(Socket in, Socket out) {
        if (in !=null) {
            try {
                in.close();
            }
            catch (Exception ex) {
            }
        }
        if (out !=null) {
            try {
                out.close();
            }
            catch (Exception ex) {
            }
        }
    }

    static void close(Socket sock) {
        if (sock !=null) {
            try {
                sock.close();
            }
            catch (Exception ex) {
            }
        }
    }

    static class Relayer implements Runnable {
        final Socket         in_sock;
        final Socket out_sock;
        final InputStream    in;
        final OutputStream   out;
        Thread         t=null;
        final java.util.List listeners=new ArrayList();
        String         name=null;

        interface Listener {
            void connectionClosed();
        }

        public Relayer(Socket in_sock, Socket out_sock, String name) throws Exception {
            this.in_sock=in_sock;
            this.out_sock=out_sock;
            this.name=name;
            in=in_sock.getInputStream();
            out=out_sock.getOutputStream();
        }

        public void addListener(Listener l) {
            if(l != null && !listeners.contains(l))
                listeners.add(l);
        }


        public void run() {
            byte[]       buf=new byte[1024];
            int          num;
            StringBuilder sb;

            try {
                while(t != null) {
                    if ((num=in.read(buf)) == -1)
                        break;

                    if (verbose) {
                        
                        //sb=new StringBuilder();


                        //sb.append("forwarding ").append(num).append(" bytes from ").append(toString(in_sock));
                        //sb.append(" to ").append(toString(out_sock));
                        // log("Proxy.Relayer.run()", sb.toString());
                        log(printRelayedData(toString(in_sock), toString(out_sock), num));
                    }
                    if (debug) {
                        sb=new StringBuilder();
                        sb.append(new String(buf, 0, num).trim());
                        log(sb.toString());
                    }

                    out.write(buf, 0, num);
                    //if(debug)
                    //    System.out.println(new String(buf));
                }
                
            }            
            catch (Exception ex) {
                log("Proxy.Relayer.run(): [" + name + "] exception=" + ex + ", in_sock=" +
                    in_sock + ", out_sock=" + out_sock);
            }
            finally {
                stop();
            }
        }

        public void start() {
            if(t == null) {
                t=new Thread(this, "Proxy.Relayer");
                t.setDaemon(true);
                t.start();
            }
        }

        public void stop() {
            t=null;
            close(in_sock);
            close(out_sock);
        }

        String toString(Socket s) {
            if(s == null) return null;
            return s.getInetAddress().getHostName() + ':' + s.getPort();
        }
        

        void notifyListeners() {
            for(Iterator it=listeners.iterator(); it.hasNext();) {
                try {
                    ((Listener)it.next()).connectionClosed();
                }
                catch(Throwable ex) {
                    ;
                }
            }
        }
    }

    static class MyInetSocketAddress extends InetSocketAddress {
        boolean is_ssl=false;

        public MyInetSocketAddress(InetAddress addr, int port) {
            super(addr, port);
        }

        public MyInetSocketAddress(InetAddress addr, int port, boolean is_ssl) {
            super(addr, port);
            this.is_ssl=is_ssl;
        }

        public MyInetSocketAddress(int port) {
            super(port);
        }

        public MyInetSocketAddress(int port, boolean is_ssl) {
            super(port);
            this.is_ssl=is_ssl;
        }

        public MyInetSocketAddress(String hostname, int port) {
            super(hostname, port);
        }

        public MyInetSocketAddress(String hostname, int port, boolean is_ssl) {
            super(hostname, port);
            this.is_ssl=is_ssl;
        }

        public boolean ssl() {
            return is_ssl;
        }

        public String toString() {
            return super.toString() + " [ssl: " + ssl() + ']';
        }
    }

    /**
     * Handles accepts on an SSLServerSocket or ServerSocket. Creates a {@link
     * Connection} for each successful accept().
     * 
     * @author bela Dec 19, 2002
     */
    class SocketAcceptor implements Runnable {
        ServerSocket        srv_sock=null;
        MyInetSocketAddress dest=null;
        

        /**
         * Create an SSLServerSocket or ServerSocket and continuously call
         * accept() on it.
         * @param sock_addr
         */
        public SocketAcceptor(MyInetSocketAddress sock_addr, MyInetSocketAddress dest) throws Exception {
            this.dest=dest;
            if(sock_addr.ssl()) {
                srv_sock=createSSLServerSocket(sock_addr);
            }
            else {
                srv_sock=createServerSocket(sock_addr);
            }
            executor.execute(this);
        }

        public void run() {
            Connection conn;
            Socket     s, dest_sock;

            while (srv_sock !=null) {
                try {
                    s=srv_sock.accept();
                    dest_sock=dest.ssl() ? createSSLSocket(dest) : createSocket(dest);
                    conn=new Connection(s, dest_sock);
                    conn.start();
                }
                catch (Exception e) {
                    log("Proxy.SSLServerSocketAcceptor.run(): exception=" + e);
                    break;
                }
            }
        }
        

        Socket createSocket(InetSocketAddress addr) throws Exception {
            return new Socket(addr.getAddress(), addr.getPort());
        }

        Socket createSSLSocket(InetSocketAddress addr) throws Exception {
            SSLSocketFactory sslsocketfactory = (SSLSocketFactory)SSLSocketFactory.getDefault();
            return sslsocketfactory.createSocket(addr.getAddress(), addr.getPort());
        }

        ServerSocket createServerSocket(InetSocketAddress addr) throws Exception {
            return new ServerSocket(addr.getPort(), 10, addr.getAddress());
        }
        
        ServerSocket createSSLServerSocket(InetSocketAddress addr) throws Exception {
            SSLServerSocketFactory sslserversocketfactory =
                (SSLServerSocketFactory)SSLServerSocketFactory.getDefault();
            SSLServerSocket sslserversocket;
            sslserversocket=(SSLServerSocket)sslserversocketfactory.createServerSocket(addr.getPort(), 10, addr.getAddress());
            return sslserversocket;
        }
    }



    /**
     * Handles an incoming SSLSocket or Socket. Looks up the destination in the
     * mapping hashmap, key is the incoming socket address. Creates an outgoing
     * socket (regular or SSL, depending on settings) and relays data between
     * incoming and outgoing sockets. Closes the connection when either incoming
     * or outgoing socket is closed, or when stop() is called.
     * 
     * @author bela Dec 19, 2002
     */
    static class Connection implements Relayer.Listener {
        Relayer in_to_out=null;
        Relayer out_to_in=null;

        /**
         * Creates an outgoing (regular or SSL) socket according to the mapping
         * table. Sets both input and output stream. Caller needs to call
         * start() after the instance has been created.
         * @param in The Socket we got as result of accept()
         * @throws Exception Thrown if either the input or output streams cannot
         * be created.
         */
        public Connection(Socket in, Socket out) throws Exception {
            in_to_out=new Relayer(in, out, "in-out");
            in_to_out.addListener(this);
            out_to_in=new Relayer(out, in, "out-in");
            out_to_in.addListener(this);
        }

        /** Starts relaying between incoming and outgoing sockets.
         * Returns immediately (thread is started). 
         * 
         */
        public void start() {
            in_to_out.start();
            out_to_in.start();
        }

        public void stop() {
            if (in_to_out !=null) {
                in_to_out.stop();
            }
            if (out_to_in !=null) {
                out_to_in.stop();
            }
        }

        public void connectionClosed() {
            stop();
        }
    }

}

   
    
    
    
    
  








Related examples in the same category

1.Create a socket without a timeout
2.Create a socket with a timeout
3.Demonstrate Sockets.
4.Socket connection and concurrent package
5.XML based message
6.ObjectInputStream and ObjectOutputStream from Socket
7.ServerSocket and Socket for Serializable object
8.String based communication between Socket
9.Get email with Socket
10.Create PrintWriter from BufferedWriter, OutputStreamWriter and Socket
11.Read from server
12.Use Socket to read and write stream
13.Connects to a server at a specified host and port. It reads text from the console and sends it to the server
14.A simple network client that establishes a network connection to a specified port on a specified host, send an optional message across the connection
15.Reading Text from a Socket
16.Writing Text to a Socket
17.Sending a POST Request Using a Socket
18.Get the Date from server
19.Transfer a file via Socket
20.Ping a server
21.Read and write through socket
22.Read float number from a Socket
23.Read Object from Socket
24.deleting messages from a POP3 mailbox based on message size and Subject line
25.A timeout feature on socket connections
26.Write Objects From Socket
27.Write Double Using Sockets
28.Download WWW Page
29.Socket Fetcher
30.Socket Address Encoder
31.Zip socket
32.This program shows how to interrupt a socket channel.
33.This program shows how to use sockets to send plain text mail messages.
34.Makes a socket connection to the atomic clock in Boulder, Colorado, and prints the time that the server sends.