package com.westudio.java.server;

import com.westudio.java.util.Numbers;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

public class DirectTunnelServlet extends TunnelServlet {

    private static final int DEFAULT_SEGMENT_SIZE = 32758;
    private static final byte[] EMPTY_CHUNK = {0, 0};

    private void onRecvRemote(InputStream is, OutputStream os) throws IOException {
        byte[] buffer  = new byte[DEFAULT_SEGMENT_SIZE + 2];
        long lastSent = 0;
        while (true) {
            long now = System.currentTimeMillis();
            int len = 0;
            try {
                len = is.read(buffer, 2, DEFAULT_SEGMENT_SIZE);
            } catch (IOException e) {/**/}
            if (len == 0) {
                if (now > lastSent + 15000) {
                    os.write(EMPTY_CHUNK);
                    os.flush();
                    lastSent = now;
                }
                try {
                    Thread.sleep(16);
                } catch (InterruptedException e) {
                }
                continue;
            }

            if (len < 0) {
                break;
            }

            os.write(buffer, 0, len + 2);
            os.flush();
            lastSent = now;
        }
    }

    @Override
    protected void doTunnel(HttpServletRequest req, HttpServletResponse res) {
        String destination = res.getHeader("Destination");
        int c = 0;

        if (destination == null || (c = destination.indexOf(":")) < 0) {
            try {
                res.sendError(HttpServletResponse.SC_BAD_REQUEST);
            } catch (IOException e) {/**/}
            return;
        }

        int port = Numbers.parseInt(destination.substring(c + 1));
        String host = destination.substring(0, c);
        final Socket socket;

        try {
            socket = new Socket(host, port);
            socket.setSoTimeout(DEFAULT_TIMEOUT);
        } catch (IOException e) {
            try {
                res.sendError(HttpServletResponse.SC_BAD_GATEWAY);
            } catch (IOException e1) {
                return;
            }
        }

        executor.execute(new Runnable() {
            @Override
            public void run() {

            }
        });
    }

}

@@ -455,16 +455,23 @@
 private 
+static 
 void onR
@@ -1391,24 +1391,159 @@
    %7D%0A    %7D%0A%0A
+    private static void onRecvClient(InputStream is, OutputStream os) %7B%0A        byte%5B%5D buffer = new byte%5BDEFAULT_SEGMENT_SIZE%5D;%0A    %7D%0A%0A
     @Overrid
@@ -1595,16 +1595,22 @@
 est req,
+ final
  HttpSer
@@ -2066,22 +2066,16 @@
         
-final 
 Socket s
@@ -2079,16 +2079,23 @@
 t socket
+ = null
 ;%0A%0A     
@@ -2397,32 +2397,71 @@
    %7D%0A        %7D%0A%0A
+        final Socket socket_ = socket;%0A
         executor
@@ -2540,16 +2540,167 @@
 run() %7B%0A
+                try %7B%0A                    onRecvRemote(socket_.getInputStream(), res.getOutputStream());%0A                %7D catch (IOException e) %7B/**/%7D
 %0A       
@@ -2718,16 +2718,18 @@
     %7D);%0A
+%0A%0A
     %7D%0A%0A%7D

update the doTunnel method….