package org.apache.tomcat.jni;

import java.util.Properties;

import java.io.*;
import java.net.*;
import java.lang.*;

/** SSL Server server example
 *
 * @author Mladen Turk
 * @version $Revision$, $Date$
 */

public class SSLServer {

    public static String serverAddr = null;
    public static int serverPort    = 0;
    public static int serverNmax    = 0;
    public static int serverNrun    = 0;
    public static long serverCtx    = 0;
    public static long serverPool   = 0;
    public static String serverCert = null;
    public static String serverKey  = null;
    public static String serverCiphers  = null;
    public static String serverPassword = null;
    public static String serverCAFile   = null;

    private static Acceptor serverAcceptor = null;

    private static Object threadLock = new Object();

    static {

        try {
            InputStream is = SSLServer.class.getResourceAsStream
                ("/org/apache/tomcat/jni/SSL.properties");
            Properties props = new Properties();
            props.load(is);
            is.close();
            serverAddr = props.getProperty("server.ip", "127.0.0.1");
            serverPort = Integer.decode(props.getProperty("server.port", "4443")).intValue();
            serverNmax = Integer.decode(props.getProperty("server.max", "1")).intValue();
            serverCert = props.getProperty("server.cert", "server.pem");
            serverKey  = props.getProperty("server.key", null);
            serverCAFile   = props.getProperty("server.cacertificate", null);
            serverCiphers  = props.getProperty("server.ciphers", "ALL");
            serverPassword = props.getProperty("server.password", null);
        }
        catch (Throwable t) {
            ; // Nothing
        }
    }

    public SSLServer()
    {
        int i;
        serverPool = Pool.create(0);
        try {
            /* Create SSL Context, one for each Virtual Host */
            serverCtx = SSLContext.make(serverPool, SSL.SSL_PROTOCOL_SSLV2 | SSL.SSL_PROTOCOL_SSLV3, SSL.SSL_MODE_SERVER);
            /* List the ciphers that the client is permitted to negotiate. */
            SSLContext.setCipherSuite(serverCtx, serverCiphers);
            /* Load Server key and certificate */
            SSLContext.setCertificate(serverCtx, serverCert, serverKey, serverPassword, SSL.SSL_AIDX_RSA);
            SSLContext.setVerify(serverCtx, SSL.SSL_CVERIFY_NONE, 10);
            serverAcceptor = new Acceptor();
            serverAcceptor.start();

        } catch (Exception e) {
            e.printStackTrace();
        }

    }
    public static void incThreads() {
        synchronized(threadLock) {
            serverNrun++;
        }
    }

    public static void decThreads() {
        synchronized(threadLock) {
            serverNrun--;
        }
    }

    /* Acceptor thread. Listens for new connections */
    private class Acceptor extends Thread {
        private long serverSock = 0;
        private long inetAddress = 0;
        private long pool = 0;
        public Acceptor() throws Exception {
            try {

                pool = Pool.create(SSLServer.serverPool);
                System.out.println("Accepting: " +  SSLServer.serverAddr + ":" +
                                   SSLServer.serverPort);
                inetAddress = Address.info(SSLServer.serverAddr, Socket.APR_INET,
                                           SSLServer.serverPort, 0,
                                           pool);
                serverSock = Socket.create(Socket.APR_INET, Socket.SOCK_STREAM,
                                           Socket.APR_PROTO_TCP, pool);
                int rc = Socket.bind(serverSock, inetAddress);
                if (rc != 0) {
                  throw(new Exception("Can't create Acceptor: bind: " + Error.strerror(rc)));
                }
                Socket.listen(serverSock, 5);
            }
            catch( Exception ex ) {
                ex.printStackTrace();
                throw(new Exception("Can't create Acceptor"));
            }
        }

        public void run() {
            int i = 0;
            try {
                while (true) {
                    long clientSock = Socket.accept(serverSock);
                    System.out.println("Accepted id: " +  i);

                    try {
                        long sa = Address.get(Socket.APR_REMOTE, clientSock);
                        Sockaddr raddr = new Sockaddr();
                        if (Address.fill(raddr, sa)) {
                            System.out.println("Remote Host: " + Address.getnameinfo(sa, 0));
                            System.out.println("Remote IP: " + Address.getip(sa) +
                                               ":" + raddr.port);
                        }
                        sa = Address.get(Socket.APR_LOCAL, clientSock);
                        Sockaddr laddr = new Sockaddr();
                        if (Address.fill(laddr, sa)) {
                            System.out.println("Local Host: " + laddr.hostname);
                            System.out.println("Local Server: " + Address.getnameinfo(sa, 0));
                            System.out.println("Local IP: " + Address.getip(sa) +
                                               ":" + laddr.port);
                        }

                    } catch (Exception e) {
                        // Ignore
                        e.printStackTrace();
                    }

                    Socket.timeoutSet(clientSock, 10000000);
                    SSLSocket.attach(SSLServer.serverCtx, clientSock);
                    i = SSLSocket.handshake(clientSock);
                    if (i == 0) {

                        Worker worker = new Worker(clientSock, i++,
                                                   this.getClass().getName());
                        SSLServer.incThreads();
                        worker.start();
                        
                    }
                    else {
                        System.out.println("Handshake error: " + SSL.getLastError());
                        Socket.destroy(clientSock);
                    }
                }
            }
            catch( Exception ex ) {
                ex.printStackTrace();
            }
        }
    }

    private class Worker extends Thread {
        private int workerId = 0;
        private long clientSock = 0;
        private byte [] wellcomeMsg = null;

        public Worker(long clientSocket, int workerId, String from) {
            this.clientSock = clientSocket;
            this.workerId = workerId;
            wellcomeMsg = ("SSLServer server id: " + this.workerId + " from " +
                           from + "\r\n").getBytes();
        }

        public void run() {
            boolean doClose = false;
            try {
                Socket.send(clientSock, wellcomeMsg, 0, wellcomeMsg.length);
                while (!doClose) {
                    /* Do a blocking read byte at a time */
                    byte [] buf = new byte[1];
                    int ret;
                    ret = Socket.recv(clientSock, buf, 0, 1);
                    if (ret != 1)
                        throw(new Exception("Socket.recv failed"));

                    if (buf[0] == '\n')
                        continue;
                    else if (buf[0] == '!') {
                        doClose = true;
                    }
                    Socket.send(clientSock, buf, 0, 1);

                    if (doClose) {
                        try {
                            byte [] msg = ("Bye from worker: " + workerId + "\r\n").getBytes();
                            Socket.send(clientSock, msg, 0, msg.length);
                        } catch(Exception e) { }

                        Socket.close(clientSock);
                    }
                }
            } catch (Exception e) {
                Socket.destroy(clientSock);
                e.printStackTrace();
            }
            Echo.decThreads();
            System.out.println("Worker: " +  workerId + " finished");
        }
    }


    public static void main(String [] args) {
        try {
            Library.initialize(null);
            SSL.initialize(null);

            SSLServer server = new SSLServer();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
 }
