/*
 * Copyright 2002 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

/**
 *
 * This class includes a proxy server that processes HTTP CONNECT requests,
 * and tunnels the data from the client to the server, once the CONNECT
 * request is accepted.
 * It is used by the TunnelThroughProxy test.
 */

import java.io.*;
import java.net.*;
import javax.net.ssl.*;
import javax.net.ServerSocketFactory;
import sun.net.www.*;

public class ProxyTunnelServer extends Thread {

    private static ServerSocket ss = null;
    /*
     * holds the registered user's username and password
     * only one such entry is maintained
     */
    private String userPlusPass;

    // client requesting for a tunnel
    private Socket clientSocket = null;

    /*
     * Origin server's address and port that the client
     * wants to establish the tunnel for communication.
     */
    private InetAddress serverInetAddr;
    private int serverPort;

    /*
     * denote whether the proxy needs to authorize
     * CONNECT requests.
     */
    static boolean needAuth = false;

    public ProxyTunnelServer() throws IOException {
        if (ss == null) {
          ss = (ServerSocket) ServerSocketFactory.getDefault().
          createServerSocket(0);
        }
    }

    public void needUserAuth(boolean auth) {
        needAuth = auth;
    }

    /*
     * register users with the proxy, by providing username and
     * password. The username and password are used for authorizing the
     * user when a CONNECT request is made and needAuth is set to true.
     */
    public void setUserAuth(String uname, String passwd) {
        userPlusPass = uname + ":" + passwd;
    }

    public void run() {
        try {
            clientSocket = ss.accept();
            processRequests();
        } catch (Exception e) {
            System.out.println("Proxy Failed: " + e);
            e.printStackTrace();
            try {
                ss.close();
            }
            catch (IOException excep) {
                System.out.println("ProxyServer close error: " + excep);
                excep.printStackTrace();
            }
          }
    }

    /*
     * Processes the CONNECT requests, if needAuth is set to true, then
     * the name and password are extracted from the Proxy-Authorization header
     * of the request. They are checked against the one that is registered,
     * if there is a match, connection is set in tunneling mode. If
     * needAuth is set to false, Proxy-Authorization checks are not made
     */
    private void processRequests() throws Exception {

        InputStream in = clientSocket.getInputStream();
        MessageHeader mheader = new MessageHeader(in);
        String statusLine = mheader.getValue(0);

        if (statusLine.startsWith("CONNECT")) {
            // retrieve the host and port info from the status-line
            // retrieveConnectInfo(statusLine);
            if (needAuth) {
                String authInfo;
                if ((authInfo = mheader.findValue("Proxy-Authorization"))
                                         != null) {
                   if (authenticate(authInfo)) {
                        needAuth = false;
                        System.out.println(
                                "Proxy: client authentication successful");
                   }
                }
            }
            respondForConnect(needAuth);

            // connection set to the tunneling mode
            if (!needAuth) {
                // doTunnel();
                /*
                 * done with tunneling, we process only one successful
                 * tunneling request
                 */
                ss.close();
            } else {
                // we may get another request with Proxy-Authorization set
                in.close();
                clientSocket.close();
                restart();
            }
        } else {
            System.out.println("proxy server: processes only "
                                   + "CONNECT method requests, recieved: "
                                   + statusLine);
        }
    }

    private void respondForConnect(boolean needAuth) throws Exception {

        OutputStream out = clientSocket.getOutputStream();
        PrintWriter pout = new PrintWriter(out);

        if (needAuth) {
            pout.println("HTTP/1.1 407 Proxy Auth Required");
            pout.println("Proxy-Authenticate: Basic realm=\"WallyWorld\"");
            pout.println();
            pout.flush();
            out.close();
        } else {
            pout.println("HTTP/1.1 500 Server Error");
            pout.println();
            pout.flush();
            out.close();
        }
    }

    private void restart() throws IOException {
         (new Thread(this)).start();
    }

    /*sc
     * note: Tunneling has to be provided in both directions, i.e
     * from client->server and server->client, even if the application
     * data may be unidirectional, SSL handshaking data flows in either
     * direction.
     */
    private void doTunnel() throws Exception {

        Socket serverSocket = new Socket(serverInetAddr, serverPort);
        ProxyTunnel clientToServer = new ProxyTunnel(
                                clientSocket, serverSocket);
        ProxyTunnel serverToClient = new ProxyTunnel(
                                serverSocket, clientSocket);
        clientToServer.start();
        serverToClient.start();
        System.out.println("Proxy: Started tunneling.......");

        clientToServer.join();
        serverToClient.join();
        System.out.println("Proxy: Finished tunneling........");

        clientToServer.close();
        serverToClient.close();
    }

    /*
     * This inner class provides unidirectional data flow through the sockets
     * by continuously copying bytes from the input socket onto the output
     * socket, until both sockets are open and EOF has not been received.
     */
    class ProxyTunnel extends Thread {
        Socket sockIn;
        Socket sockOut;
        InputStream input;
        OutputStream output;

        public ProxyTunnel(Socket sockIn, Socket sockOut)
        throws Exception {
            this.sockIn = sockIn;
            this.sockOut = sockOut;
            input = sockIn.getInputStream();
            output = sockOut.getOutputStream();
        }

        public void run() {
            int BUFFER_SIZE = 400;
            byte[] buf = new byte[BUFFER_SIZE];
            int bytesRead = 0;
            int count = 0;  // keep track of the amount of data transfer

            try {
                while ((bytesRead = input.read(buf)) >= 0) {
                    output.write(buf, 0, bytesRead);
                    output.flush();
                    count += bytesRead;
                }
            } catch (IOException e) {
                /*
                 * The peer end has closed the connection
                 * we will close the tunnel
                 */
                close();
              }
        }

        public void close() {
            try {
                if (!sockIn.isClosed())
                    sockIn.close();
                if (!sockOut.isClosed())
                    sockOut.close();
            } catch (IOException ignored) { }
        }
    }

    /*
     ***************************************************************
     *                  helper methods follow
     ***************************************************************
     */

    /*
     * This method retrieves the hostname and port of the destination
     * that the connect request wants to establish a tunnel for
     * communication.
     * The input, connectStr is of the form:
     *                          CONNECT server-name:server-port HTTP/1.x
     */
    private void retrieveConnectInfo(String connectStr) throws Exception {
        int starti;
        int endi;
        String connectInfo;
        String serverName = null;
        try {
            starti = connectStr.indexOf(' ');
            endi = connectStr.lastIndexOf(' ');
            connectInfo = connectStr.substring(starti+1, endi).trim();
            // retrieve server name and port
            endi = connectInfo.indexOf(':');
            serverName = connectInfo.substring(0, endi);
            serverPort = Integer.parseInt(connectInfo.substring(endi+1));
        } catch (Exception e) {
            throw new IOException("Proxy recieved a request: "
                                        + connectStr);
          }
        serverInetAddr = InetAddress.getByName(serverName);
    }

    public int getPort() {
        return ss.getLocalPort();
    }

    /*
     * do "basic" authentication, authInfo is of the form:
     *                                  Basic <encoded username":"password>
     * reference RFC 2617
     */
    private boolean authenticate(String authInfo) throws IOException {
        boolean matched = false;
        try {
            authInfo.trim();
            int ind = authInfo.indexOf(' ');
            String recvdUserPlusPass = authInfo.substring(ind + 1).trim();
            // extract encoded (username:passwd
            if (userPlusPass.equals(
                                new String(
                                (new sun.misc.BASE64Decoder()).
                                decodeBuffer(recvdUserPlusPass)
                                ))) {
                matched = true;
            }
        } catch (Exception e) {
              throw new IOException(
                "Proxy received invalid Proxy-Authorization value: "
                 + authInfo);
          }
        return matched;
    }
}
