import javax.net.ssl.*;
import javax.net.ssl.SSLEngineResult.*;
import java.io.*;
import java.security.*;
import java.nio.*;

 
 public class SSLEngineServerReadFile {

    private static String proto = System.getProperty("proto","TLS");

    private static boolean debug = false;

    private SSLContext sslc;

    private SSLEngine serverEngine;     // server Engine
    private ByteBuffer serverIn;        // read side of serverEngine
    private ByteBuffer clientOut;        // read side of serverEngine

    private ByteBuffer cTOs;            // "reliable" transport client->server

    /*
     * The following is to set up the keystores.
     */
    private static String keyStoreFile = "testkeys";
    private static String trustStoreFile = "testkeys";
    private static String passwd = "passphrase";

    /*
     * Main entry point for this demo.
     */
    public static void main(String args[]) throws Exception {
        if (debug) {
            System.setProperty("javax.net.debug", "all");
        }

        byte[] payload = new byte[0];
        if (args.length>0) {
            FileInputStream fis = new FileInputStream(args[0]);
            payload = fis.readAllBytes();
            fis.close();
        }
        System.out.println("payload len:"+payload.length);   

        SSLEngineServerReadFile demo = new SSLEngineServerReadFile();
        demo.runDemo(payload);

        System.out.println("Demo Completed.");
    }

    static SSLEngineServerReadFile fuzzdemoref = null;

    /*
     * Create an initialized SSLContext to use for this demo.
     */

     public SSLEngineServerReadFile() throws Exception {

        KeyStore ks = KeyStore.getInstance("JKS");
        KeyStore ts = KeyStore.getInstance("JKS");

        char[] passphrase = passwd.toCharArray();

        ks.load(new FileInputStream(keyStoreFile), passphrase);
        ts.load(new FileInputStream(trustStoreFile), passphrase);

        KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
        kmf.init(ks, passphrase);

        TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
        tmf.init(ts);

        SSLContext sslCtx = SSLContext.getInstance(proto);

        sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);

        sslc = sslCtx;
    }



    private void runDemo(byte[] injected) throws Exception {

        createSSLEngines();
        createBuffers();

        cTOs = ByteBuffer.wrap(injected);

        System.out.println("injecting client hello");
        
        for (int i = 0 ; i < 10 ; i++) { //retry if survived
            SSLEngineResult serverResult = serverEngine.unwrap(cTOs, serverIn);
            System.out.println("server unwrap: "+ serverResult);
            runDelegatedTasks(serverResult, serverEngine);
        }
    }

    private void createSSLEngines() throws Exception {

        serverEngine = sslc.createSSLEngine();
        serverEngine.setUseClientMode(false);
        serverEngine.setNeedClientAuth(true);

    }


    private void createBuffers() {

        serverIn = ByteBuffer.allocateDirect(65536);

        cTOs = ByteBuffer.allocateDirect(65536);

        clientOut = ByteBuffer.wrap("Hi Server, I'm Client".getBytes());
    }

    private static void runDelegatedTasks(SSLEngineResult result,
            SSLEngine engine) throws Exception {

        if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
            Runnable runnable;
            while ((runnable = engine.getDelegatedTask()) != null) {
                System.out.println("\trunning delegated task...");
                runnable.run();
            }
            HandshakeStatus hsStatus = engine.getHandshakeStatus();
            if (hsStatus == HandshakeStatus.NEED_TASK) {
                throw new Exception(
                    "handshake shouldn't need additional tasks");
            }
            System.out.println("\tnew HandshakeStatus: " + hsStatus);
        }
    }



}