package tcpproxy;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;

public class HandlerProxy implements Handler {

    @Override
    public void process(SelectionKey key) throws IOException {
        Holder holder = (Holder) key.attachment();
        if (holder == null) return;

        if (key.channel() == holder.clientChannel) {
            if (key.isValid() && key.isReadable()) {
                // client -> buffer
                int read = holder.clientChannel.read(holder.serverBuffer);

                if (read == -1) {
                    System.out.println("Client decides to close.");
                    holder.close();
                } else {
                    holder.serverBuffer.flip();
                    holder.serverBufferState = BufferState.READY_TO_READ;
                    holder.register(key.selector());
                    System.out.println("Red from client " + read + " bytes");
                }
            }

            if (key.isValid() && key.isWritable()) {
                // buffer -> client
                int write = holder.clientChannel.write(holder.clientBuffer);
                holder.clientBuffer.clear();
                holder.clientBufferState = BufferState.READY_TO_WRITE;
                holder.register(key.selector());
                System.out.println("Wrote to client " + write + " bytes");
            }
        }

        if (key.channel() == holder.serverChannel) {
            if (key.isValid() && key.isReadable()) {
                int read = holder.serverChannel.read(holder.clientBuffer);

                if (read == -1) {
                    System.out.println("Server decides to close.");
                    holder.close();
                } else {
                    holder.clientBuffer.flip();
                    holder.clientBufferState = BufferState.READY_TO_READ;
                    holder.register(key.selector());
                    System.out.println("Red from server " + read + " bytes");
                }
            }

            if (key.isValid() && key.isWritable()) {
                int write = holder.serverChannel.write(holder.serverBuffer);
                holder.serverBuffer.clear();
                holder.serverBufferState = BufferState.READY_TO_WRITE;
                holder.register(key.selector());
                System.out.println("Wrote to server " + write + " bytes");
            }
        }
    }

    public static class Holder {

        public SocketChannel clientChannel;
        public SocketChannel serverChannel;

        public ByteBuffer serverBuffer;
        public BufferState serverBufferState;

        public ByteBuffer clientBuffer;
        public BufferState clientBufferState;

        public void close() throws IOException {
            clientChannel.close();
            serverChannel.close();

            System.out.println("Holder was closed.");
        }

        public void register(Selector selector) throws ClosedChannelException {
            int clientOps = 0;
            if (serverBufferState == BufferState.READY_TO_WRITE) clientOps |= SelectionKey.OP_READ;
            if (clientBufferState == BufferState.READY_TO_READ) clientOps |= SelectionKey.OP_WRITE;
            clientChannel.register(selector, clientOps, this);

            int serverOps = 0;
            if (clientBufferState == BufferState.READY_TO_WRITE) serverOps |= SelectionKey.OP_READ;
            if (serverBufferState == BufferState.READY_TO_READ) serverOps |= SelectionKey.OP_WRITE;
            serverChannel.register(selector, serverOps, this);

            System.out.println("Holder was registered client " + clientOps + " server " + serverOps);
        }

    }

    public static enum BufferState {

        READY_TO_WRITE, READY_TO_READ

    }

}
@@ -287,24 +287,75 @@
 andler %7B%0D%0A%0D%0A
+    private static final boolean DEBUG = false;%0D%0A%0D%0A
     @Overrid
@@ -357,16 +357,16 @@
 erride%0D%0A
-
     publ
@@ -781,32 +781,43 @@
                 
+ if (DEBUG)
  System.out.prin
@@ -1102,32 +1102,43 @@
                 
+ if (DEBUG)
  System.out.prin
@@ -1561,32 +1561,43 @@
 %0A               
+ if (DEBUG)
  System.out.prin
@@ -1901,32 +1901,43 @@
                 
+ if (DEBUG)
  System.out.prin
@@ -2222,32 +2222,43 @@
                 
+ if (DEBUG)
  System.out.prin
@@ -2644,32 +2644,43 @@
 %0A               
+ if (DEBUG)
  System.out.prin
@@ -3194,32 +3194,43 @@
 ;%0D%0A%0D%0A           
+ if (DEBUG)
  System.out.prin
@@ -3943,32 +3943,32 @@
 rOps, this);%0D%0A%0D%0A
-
             Syst
@@ -3962,16 +3962,27 @@
         
+ if (DEBUG)
  System.

Disable DEBUG logging.