/*
 * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
import java.net.*;
import java.io.*;
import java.util.HashMap;

public class SocksServer extends Thread {
    // Some useful SOCKS constant

    static final int PROTO_VERS4        = 4;
    static final int PROTO_VERS         = 5;
    static final int DEFAULT_PORT       = 1080;

    static final int NO_AUTH            = 0;
    static final int GSSAPI             = 1;
    static final int USER_PASSW         = 2;
    static final int NO_METHODS         = -1;

    static final int CONNECT            = 1;
    static final int BIND               = 2;
    static final int UDP_ASSOC          = 3;

    static final int IPV4               = 1;
    static final int DOMAIN_NAME        = 3;
    static final int IPV6               = 4;

    static final int REQUEST_OK         = 0;
    static final int GENERAL_FAILURE    = 1;
    static final int NOT_ALLOWED        = 2;
    static final int NET_UNREACHABLE    = 3;
    static final int HOST_UNREACHABLE   = 4;
    static final int CONN_REFUSED       = 5;
    static final int TTL_EXPIRED        = 6;
    static final int CMD_NOT_SUPPORTED  = 7;
    static final int ADDR_TYPE_NOT_SUP  = 8;

    private int port;
    private ServerSocket server;
    private boolean useV4 = false;
    private HashMap<String,String> users = new HashMap<>();
    private volatile boolean done = false;
    // Inner class to handle protocol with client
    // This is the bulk of the work (protocol handler)
    class ClientHandler extends Thread {
        private InputStream in;
        private OutputStream out;
        private Socket client;
        private Socket dest;

        // Simple tunneling class, moving bits from one stream to another

        class Tunnel extends Thread {
            private InputStream tin;
            private OutputStream tout;

            Tunnel(InputStream in, OutputStream out) {
                tin = in;
                tout = out;
            }

            public void run() {
                int b;
                while (true) {
                    try {
                        b = tin.read();
                        if (b == -1) {
                            tin.close();
                            tout.close();
                            return;
                        }
                        tout.write(b);
                    } catch (IOException e) {
                        // actually exit from the thread
                        return;
                    }
                }
            }
        }

        ClientHandler(Socket s) throws IOException {
            client = s;
            in = client.getInputStream();
            out = client.getOutputStream();
        }

        private void readBuf(InputStream is, byte[] buf) throws IOException {
            int l = buf.length;
            int count = 0;
            int i;
            do {
                i = is.read(buf, count, l - count);
                if (i == -1)
                    throw new IOException("unexpected EOF");
                count += i;
            } while (count < l);
        }


        private boolean userPassAuth() throws IOException {
            int ver = in.read();
            int ulen = in.read();
            if (ulen <= 0)
                throw new SocketException("SOCKS protocol error");
            byte[] buf = new byte[ulen];
            readBuf(in, buf);
            String uname = new String(buf);
            String password = null;
            ulen = in.read();
            if (ulen < 0)
                throw new SocketException("SOCKS protocol error");
            if (ulen > 0) {
                buf = new byte[ulen];
                readBuf(in, buf);
                password = new String(buf);
            }
            // Check username/password validity here
            System.err.println("User: '" + uname);
            System.err.println("PSWD: '" + password);
            if (users.containsKey(uname)) {
                String p1 = users.get(uname);
                System.err.println("p1 = " + p1);
                if (p1.equals(password)) {
                    out.write(PROTO_VERS);
                    out.write(REQUEST_OK);
                    out.flush();
                    return true;
                }
            }
            out.write(PROTO_VERS);
            out.write(NOT_ALLOWED);
            out.flush();
            return false;
        }

        private void purge() throws IOException {
            boolean done = false;
            int i = 0;
            client.setSoTimeout(1000);
            while(!done && i != -1) {
                try {
                    i = in.read();
                } catch(IOException e) {
                    done = true;
                }
            }
        }


        // Handle the SOCKS version 4 protocl

        private void getRequestV4() throws IOException {
            int ver = in.read();
            int cmd = in.read();
            if (ver == -1 || cmd == -1) {
                // EOF
                in.close();
                out.close();
                return;
            }

            if (ver != 0 && ver != 4) {
                out.write(PROTO_VERS4);
                out.write(91); // Bad Request
                out.write(0);
                out.write(0);
                out.write(0);
                out.write(0);
                out.write(0);
                out.write(0);
                out.write(0);
                out.flush();
                purge();
                out.close();
                in.close();
                return;
            }

            if (cmd == CONNECT) {
                int port = ((in.read() & 0xff) << 8);
                port += (in.read() & 0xff);
                byte[] buf = new byte[4];
                readBuf(in, buf);
                InetAddress addr = InetAddress.getByAddress(buf);
                // We don't use the username...
                int c;
                do {
                    c = (in.read() & 0xff);
                } while (c!=0);
                boolean ok = true;
                try {
                    dest = new Socket(addr, port);
                } catch (IOException e) {
                    ok = false;
                }
                if (!ok) {
                    out.write(PROTO_VERS4);
                    out.write(91);
                    out.write(0);
                    out.write(0);
                    out.write(buf);
                    out.flush();
                    purge();
                    out.close();
                    in.close();
                    return;
                }
                out.write(PROTO_VERS4);
                out.write(90); // Success
                out.write((port >> 8) & 0xff);
                out.write(port & 0xff);
                out.write(buf);
                out.flush();
                InputStream in2 = dest.getInputStream();
                OutputStream out2 = dest.getOutputStream();

                Tunnel tunnel = new Tunnel(in2, out);
                tunnel.start();

                int b = 0;
                do {
                    try {
                        b = in.read();
                        if (b == -1) {
                            in.close();
                            out2.close();
                            return;
                        }
                        out2.write(b);
                    } catch (IOException ex) {
                    }
                } while (!client.isClosed());
            }
        }


        // Negociate the authentication scheme with the client
        private void negociate() throws IOException {
            int ver = in.read();
            int n = in.read();
            byte[] buf = null;
            if (n > 0) {
                buf = new byte[n];
                readBuf(in, buf);
            }
            int scheme = NO_AUTH;
            for (int i = 0; i < n; i++)
                if (buf[i] == USER_PASSW)
                    scheme = USER_PASSW;
            out.write(PROTO_VERS);
            out.write(scheme);
            out.flush();
            if (scheme == USER_PASSW)
                userPassAuth();
        }

        // Send error message then close the streams
        private void sendError(int code) {
            try {
                out.write(PROTO_VERS);
                out.write(code);
                out.write(0);
                out.write(IPV4);
                for (int i=0; i<6; i++)
                    out.write(0);
                out.flush();
                out.close();
            } catch (IOException ex) {
            }
        }

        // Actually connect the proxy to the destination then initiate tunneling

        private void doConnect(InetSocketAddress addr) throws IOException {
            dest = new Socket();
            try {
                dest.connect(addr, 10000);
            } catch (SocketTimeoutException ex) {
                sendError(HOST_UNREACHABLE);
                return;
            } catch (ConnectException cex) {
                sendError(CONN_REFUSED);
                return;
            }
            // Success
            InetAddress iadd = addr.getAddress();
            if (iadd instanceof Inet4Address) {
                out.write(PROTO_VERS);
                out.write(REQUEST_OK);
                out.write(0);
                out.write(IPV4);
                out.write(iadd.getAddress());
            } else if (iadd instanceof Inet6Address) {
                out.write(PROTO_VERS);
                out.write(REQUEST_OK);
                out.write(0);
                out.write(IPV6);
                out.write(iadd.getAddress());
            } else {
                sendError(GENERAL_FAILURE);
                return;
            }
            out.write((addr.getPort() >> 8) & 0xff);
            out.write((addr.getPort() >> 0) & 0xff);
            out.flush();

            InputStream in2 = dest.getInputStream();
            OutputStream out2 = dest.getOutputStream();

            Tunnel tunnel = new Tunnel(in2, out);
            tunnel.start();

            int b = 0;
            do {
                // Note that the socket might be closed from another thread (the tunnel)
                try {
                    b = in.read();
                    if (b == -1) {
                        in.close();
                        out2.close();
                        return;
                    }
                    out2.write(b);
                } catch(IOException ioe) {
                }
            } while (!client.isClosed());
        }

        private void doBind(InetSocketAddress addr) throws IOException {
            ServerSocket svr = new ServerSocket();
            svr.bind(null);
            InetSocketAddress bad = (InetSocketAddress) svr.getLocalSocketAddress();
            out.write(PROTO_VERS);
            out.write(REQUEST_OK);
            out.write(0);
            out.write(IPV4);
            out.write(bad.getAddress().getAddress());
            out.write((bad.getPort() >> 8) & 0xff);
            out.write((bad.getPort() & 0xff));
            out.flush();
            dest = svr.accept();
            bad = (InetSocketAddress) dest.getRemoteSocketAddress();
            out.write(PROTO_VERS);
            out.write(REQUEST_OK);
            out.write(0);
            out.write(IPV4);
            out.write(bad.getAddress().getAddress());
            out.write((bad.getPort() >> 8) & 0xff);
            out.write((bad.getPort() & 0xff));
            out.flush();
            InputStream in2 = dest.getInputStream();
            OutputStream out2 = dest.getOutputStream();

            Tunnel tunnel = new Tunnel(in2, out);
            tunnel.start();

            int b = 0;
            do {
                // Note that the socket might be close from another thread (the tunnel)
                try {
                    b = in.read();
                    if (b == -1) {
                        in.close();
                        out2.close();
                        return;
                    }
                    out2.write(b);
                } catch(IOException ioe) {
                }
            } while (!client.isClosed());

        }

        // Handle the SOCKS v5 requests

        private void getRequest() throws IOException {
            int ver = in.read();
            int cmd = in.read();
            if (ver == -1 || cmd == -1) {
                in.close();
                out.close();
                return;
            }
            int rsv = in.read();
            int atyp = in.read();
            String addr = null;
            int port = 0;

            switch(atyp) {
            case IPV4:
                {
                byte[] buf = new byte[4];
                readBuf(in, buf);
                int i = 0;
                StringBuffer sb = new StringBuffer();
                for (i = 0; i < 4; i++) {
                    sb.append(buf[i]&0xff);
                    if (i < 3)
                        sb.append('.');
                }
                addr = sb.toString();
                }
                break;
            case DOMAIN_NAME:
                {
                int i = in.read();
                byte[] buf = new byte[i];
                readBuf(in, buf);
                addr = new String(buf);
                }
                break;
            case IPV6:
                {
                byte[] buf = new byte[16];
                readBuf(in, buf);
                int i = 0;
                StringBuffer sb = new StringBuffer();
                for (i = 0; i<16; i++) {
                    sb.append(Integer.toHexString(buf[i]&0xff));
                    if (i < 15)
                        sb.append(':');
                }
                addr = sb.toString();
                }
                break;
            }

            port = ((in.read()&0xff) << 8);
            port += (in.read()&0xff);

            InetSocketAddress socAddr = new InetSocketAddress(addr, port);
            switch(cmd) {
            case CONNECT:
                doConnect(socAddr);
                break;
            case BIND:
                doBind(socAddr);
                break;
            case UDP_ASSOC:
                // doUDP(socAddr);
                break;
            }
        }

        public void run() {
            String line = null;
            try {
                if (useV4) {
                    getRequestV4();
                } else {
                    negociate();
                    getRequest();
                }
            } catch (IOException ex) {
                try {
                    sendError(GENERAL_FAILURE);
                } catch (Exception e) {
                }
            } finally {
                try {
                    client.close();
                } catch (IOException e2) {
                }
            }
        }

    }

    public SocksServer(int port, boolean v4) throws IOException {
        this(port);
        this.useV4 = v4;
    }

    public SocksServer(int port) throws IOException {
        this.port = port;
        server = new ServerSocket();
        if (port == 0) {
            server.bind(null);
            this.port = server.getLocalPort();
        } else {
            server.bind(new InetSocketAddress(port));
        }
    }

    public SocksServer() throws IOException {
        this (DEFAULT_PORT);
    }

    public void addUser(String user, String passwd) {
        users.put(user, passwd);
    }

    public int getPort() {
        return port;
    }

    public void terminate() {
        done = true;
        try { server.close(); } catch (IOException unused) {}
    }

    public void run() {
        ClientHandler cl = null;
        while (!done) {
            try {
                Socket s = server.accept();
                cl = new ClientHandler(s);
                cl.start();
            } catch (IOException ex) {
                if (cl != null)
                    cl.interrupt();
            }
        }
    }
}
